From 46eca5f54b62e9ced10fa38c85d6aaa70f3aaed5 Mon Sep 17 00:00:00 2001 From: YourMJK <37852512+YourMJK@users.noreply.github.com> Date: Mon, 16 Jun 2025 09:44:08 +0200 Subject: [PATCH 01/36] Fix typo in documentation for RSA private key constructors (#362) Fixed the documentation comment for the constructors * `init(unsafePEMRepresentation:)` * `init(unsafeDERRepresentation:)` of **`_RSA.Signing.PrivateKey`** which said "*public* key" instead of "*private* key". ### Modifications: No code changes. --- Sources/_CryptoExtras/RSA/RSA.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/_CryptoExtras/RSA/RSA.swift b/Sources/_CryptoExtras/RSA/RSA.swift index df6a5876b..c0acdbb4a 100644 --- a/Sources/_CryptoExtras/RSA/RSA.swift +++ b/Sources/_CryptoExtras/RSA/RSA.swift @@ -179,7 +179,7 @@ extension _RSA.Signing { } } - /// Construct an RSA public key from a PEM representation. + /// Construct an RSA private key from a PEM representation. /// /// This constructor supports key sizes of 1024 bits or more. Users should validate that key sizes are appropriate /// for their use-case. @@ -204,7 +204,7 @@ extension _RSA.Signing { } } - /// Construct an RSA public key from a DER representation. + /// Construct an RSA private key from a DER representation. /// /// This constructor supports key sizes of 1024 bits or more. Users should validate that key sizes are appropriate /// for their use-case. From dbb455989c5bc33e4a524741f264880ef3d399af Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Thu, 19 Jun 2025 16:25:31 +0100 Subject: [PATCH 02/36] Make EllipticCurvePoint and ArbitraryPrecisionInteger Sendable (#366) Motivation Both of these types should be CoW data structures that are inherently Sendable. This will make programming with them substantially easier. Modifications - ArbitraryPrecisionInteger gets marked @unchecked Sendable - Refactor EllipticCurvePoint to become a CoW value type - Make EllipticCurvePoint @unchecked Sendable Results Easier to use types --- .../EC/EllipticCurvePoint.swift | 512 +++++++++++------- .../Util/ArbitraryPrecisionInteger.swift | 2 +- .../EllipticCurvePointTests.swift | 60 ++ 3 files changed, 374 insertions(+), 200 deletions(-) create mode 100644 Tests/CryptoBoringWrapperTests/EllipticCurvePointTests.swift diff --git a/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift b/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift index 5ca515aa4..266886237 100644 --- a/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift +++ b/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift @@ -17,100 +17,55 @@ import protocol Foundation.ContiguousBytes import struct Foundation.Data -/// A wrapper around BoringSSL's EC_POINT with some lifetime management. +/// A wrapper around BoringSSL's EC_POINT with some lifetime management and value semantics. @usableFromInline @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -package final class EllipticCurvePoint { - @usableFromInline var _basePoint: OpaquePointer - +package struct EllipticCurvePoint: @unchecked Sendable { @usableFromInline - package init(copying pointer: OpaquePointer, on group: BoringSSLEllipticCurveGroup) throws { - self._basePoint = try group.withUnsafeGroupPointer { groupPtr in - guard let pointPtr = CCryptoBoringSSL_EC_POINT_dup(pointer, groupPtr) else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - return pointPtr - } - } + var backing: Backing @usableFromInline - package convenience init( - copying other: EllipticCurvePoint, - on group: BoringSSLEllipticCurveGroup - ) - throws - { - try self.init(copying: other._basePoint, on: group) + package init(copying pointer: OpaquePointer, on group: BoringSSLEllipticCurveGroup) throws { + self.backing = try .init(copying: pointer, on: group) } @usableFromInline package init(_pointAtInfinityOn group: BoringSSLEllipticCurveGroup) throws { - self._basePoint = try group.withUnsafeGroupPointer { groupPtr in - guard let pointPtr = CCryptoBoringSSL_EC_POINT_new(groupPtr) else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - return pointPtr - } + self.backing = try .init(_pointAtInfinityOn: group) } @usableFromInline package init(_generatorOf groupPtr: OpaquePointer) throws { - guard - let generatorPtr = CCryptoBoringSSL_EC_GROUP_get0_generator(groupPtr), - let pointPtr = CCryptoBoringSSL_EC_POINT_dup(generatorPtr, groupPtr) - else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - self._basePoint = pointPtr + self.backing = try .init(_generatorOf: groupPtr) } @usableFromInline - package convenience init( + package init( multiplying scalar: ArbitraryPrecisionInteger, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.init(_pointAtInfinityOn: group) - try group.withUnsafeGroupPointer { groupPtr in - try scalar.withUnsafeBignumPointer { scalarPtr in - guard CCryptoBoringSSL_EC_POINT_mul(groupPtr, self._basePoint, scalarPtr, nil, nil, context?.bnCtx) == 1 - else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - } - } - } - - deinit { - CCryptoBoringSSL_EC_POINT_free(self._basePoint) + self.backing = try .init(multiplying: scalar, on: group, context: context) } @usableFromInline - package func multiply( + package mutating func multiply( by rhs: ArbitraryPrecisionInteger, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.withPointPointer { selfPtr in - try rhs.withUnsafeBignumPointer { rhsPtr in - try group.withUnsafeGroupPointer { groupPtr in - guard CCryptoBoringSSL_EC_POINT_mul(groupPtr, selfPtr, nil, selfPtr, rhsPtr, context?.bnCtx) != 0 - else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - } - } - } + try self.cowIfNeeded(on: group) + try self.backing.multiply(by: rhs, on: group, context: context) } @usableFromInline - package convenience init( + package init( multiplying lhs: EllipticCurvePoint, by rhs: ArbitraryPrecisionInteger, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.init(copying: lhs, on: group) + self = lhs try self.multiply(by: rhs, on: group, context: context) } @@ -120,48 +75,38 @@ package final class EllipticCurvePoint { on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - guard isKnownUniquelyReferenced(&self) else { - return try EllipticCurvePoint(multiplying: self, by: rhs, on: group, context: context) - } try self.multiply(by: rhs, on: group, context: context) return self } @usableFromInline package static func multiplying( - _ lhs: EllipticCurvePoint, + _ lhs: consuming EllipticCurvePoint, by rhs: ArbitraryPrecisionInteger, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - try EllipticCurvePoint(multiplying: lhs, by: rhs, on: group, context: context) + try lhs.multiplying(by: rhs, on: group, context: context) } @usableFromInline - package func add( + package mutating func add( _ rhs: EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.withPointPointer { selfPtr in - try group.withUnsafeGroupPointer { groupPtr in - try rhs.withPointPointer { rhsPtr in - guard CCryptoBoringSSL_EC_POINT_add(groupPtr, selfPtr, selfPtr, rhsPtr, context?.bnCtx) != 0 else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - } - } - } + try self.cowIfNeeded(on: group) + try self.backing.add(rhs, on: group, context: context) } @usableFromInline - package convenience init( + package init( adding lhs: EllipticCurvePoint, _ rhs: EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.init(copying: lhs, on: group) + self = lhs try self.add(rhs, on: group, context: context) } @@ -171,78 +116,77 @@ package final class EllipticCurvePoint { on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - guard isKnownUniquelyReferenced(&self) else { - return try EllipticCurvePoint(adding: self, rhs, on: group, context: context) - } try self.add(rhs, on: group, context: context) return self } @usableFromInline package static func adding( - _ lhs: EllipticCurvePoint, + _ lhs: consuming EllipticCurvePoint, _ rhs: EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - try EllipticCurvePoint(adding: lhs, rhs, on: group, context: context) + try lhs.add(rhs, on: group, context: context) + return lhs } @usableFromInline - package func invert(on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil) throws { - try self.withPointPointer { selfPtr in - try group.withUnsafeGroupPointer { groupPtr in - guard CCryptoBoringSSL_EC_POINT_invert(groupPtr, selfPtr, context?.bnCtx) != 0 else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - } - } + package mutating func invert( + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws { + try self.cowIfNeeded(on: group) + try self.backing.invert(on: group, context: context) } @usableFromInline - package convenience init( + package init( inverting point: EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.init(copying: point, on: group) + self = point try self.invert(on: group, context: context) } @usableFromInline - package func inverting( + package consuming func inverting( on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - try EllipticCurvePoint(inverting: self, on: group, context: context) + try self.invert(on: group, context: context) + return self } @usableFromInline package static func inverting( - _ point: EllipticCurvePoint, + _ point: consuming EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - try EllipticCurvePoint(inverting: point, on: group, context: context) + try point.invert(on: group, context: context) + return point } @usableFromInline - package func subtract( - _ rhs: EllipticCurvePoint, + package mutating func subtract( + _ rhs: consuming EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { + try self.cowIfNeeded(on: group) try self.add(rhs.inverting(on: group), on: group, context: context) } @usableFromInline - package convenience init( - subtracting rhs: EllipticCurvePoint, - from lhs: EllipticCurvePoint, + package init( + subtracting rhs: consuming EllipticCurvePoint, + from lhs: consuming EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.init(copying: lhs, on: group) + self = lhs try self.subtract(rhs, on: group, context: context) } @@ -252,54 +196,28 @@ package final class EllipticCurvePoint { on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - guard isKnownUniquelyReferenced(&self) else { - return try EllipticCurvePoint(subtracting: rhs, from: self, on: group, context: context) - } try self.subtract(rhs, on: group, context: context) return self } @usableFromInline package static func subtracting( - _ rhs: EllipticCurvePoint, - from lhs: EllipticCurvePoint, + _ rhs: consuming EllipticCurvePoint, + from lhs: consuming EllipticCurvePoint, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws -> EllipticCurvePoint { - try EllipticCurvePoint(subtracting: rhs, from: lhs, on: group, context: context) + try lhs.subtract(rhs, on: group, context: context) + return lhs } @usableFromInline - package convenience init( + package init( hashing msg: MessageBytes, to group: BoringSSLEllipticCurveGroup, domainSeparationTag: DSTBytes ) throws { - let hashToCurveFunction = - switch group.curveName { - case .p256: CCryptoBoringSSLShims_EC_hash_to_curve_p256_xmd_sha256_sswu - case .p384: CCryptoBoringSSLShims_EC_hash_to_curve_p384_xmd_sha384_sswu - case .p521: throw CryptoBoringWrapperError.invalidParameter // BoringSSL has no P521 hash_to_curve API. - case .none: throw CryptoBoringWrapperError.internalBoringSSLError() - } - - try self.init(_pointAtInfinityOn: group) - try msg.withUnsafeBytes { msgPtr in - try group.withUnsafeGroupPointer { groupPtr in - try domainSeparationTag.withUnsafeBytes { dstPtr in - guard - hashToCurveFunction( - groupPtr, - self._basePoint, - dstPtr.baseAddress, - dstPtr.count, - msgPtr.baseAddress, - msgPtr.count - ) == 1 - else { throw CryptoBoringWrapperError.internalBoringSSLError() } - } - } - } + self.backing = try .init(hashing: msg, to: group, domainSeparationTag: domainSeparationTag) } @usableFromInline @@ -308,110 +226,289 @@ package final class EllipticCurvePoint { on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) -> Bool { - self.withPointPointer { selfPtr in - group.withUnsafeGroupPointer { groupPtr in - rhs.withPointPointer { rhsPtr in - switch CCryptoBoringSSL_EC_POINT_cmp(groupPtr, selfPtr, rhsPtr, context?.bnCtx) { - case 0: return true - case 1: return false - default: - // EC_POINT_cmp returns an error when comparing points on different groups. - // We treat that as not equal, so we'll just clear the error and return false. - CCryptoBoringSSL_ERR_clear_error() - return false - } - } - } - } + self.backing.isEqual(to: rhs, on: group, context: context) } @usableFromInline - package convenience init( + package init( x962Representation bytes: Bytes, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil ) throws { - try self.init(_pointAtInfinityOn: group) - guard - group.withUnsafeGroupPointer({ groupPtr in - bytes.withUnsafeBytes { dataPtr in - CCryptoBoringSSL_EC_POINT_oct2point( - groupPtr, - self._basePoint, - dataPtr.baseAddress, - dataPtr.count, - context?.bnCtx - ) - } - }) == 1 - else { - throw CryptoBoringWrapperError.invalidParameter - } + self.backing = try .init(x962Representation: bytes, on: group, context: context) } @usableFromInline - package func x962RepresentationByteCount( + package func x962Representation( compressed: Bool, on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil - ) throws -> Int { - let numBytesNeeded = group.withUnsafeGroupPointer { groupPtr in - CCryptoBoringSSL_EC_POINT_point2oct( - groupPtr, - self._basePoint, - compressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED, - nil, - 0, - context?.bnCtx - ) - } - guard numBytesNeeded != 0 else { - throw CryptoBoringWrapperError.internalBoringSSLError() + ) throws -> Data { + try self.backing.x962Representation(compressed: compressed, on: group, context: context) + } + + private mutating func cowIfNeeded(on group: BoringSSLEllipticCurveGroup) throws { + if !isKnownUniquelyReferenced(&self.backing) { + self.backing = try .init(copying: self.backing, on: group) } - return numBytesNeeded } +} +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) +extension EllipticCurvePoint { @usableFromInline - package func x962Representation( - compressed: Bool, - on group: BoringSSLEllipticCurveGroup, - context: FiniteFieldArithmeticContext? = nil - ) throws -> Data { - let numBytesNeeded = try self.x962RepresentationByteCount(compressed: compressed, on: group, context: context) + final class Backing { + @usableFromInline + let _basePoint: OpaquePointer - var buf = Data(repeating: 0, count: numBytesNeeded) + fileprivate init(copying pointer: OpaquePointer, on group: BoringSSLEllipticCurveGroup) throws { + self._basePoint = try group.withUnsafeGroupPointer { groupPtr in + guard let pointPtr = CCryptoBoringSSL_EC_POINT_dup(pointer, groupPtr) else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + return pointPtr + } + } - let numBytesWritten = group.withUnsafeGroupPointer { groupPtr in - buf.withUnsafeMutableBytes { bufPtr in - CCryptoBoringSSLShims_EC_POINT_point2oct( + fileprivate convenience init( + copying other: Backing, + on group: BoringSSLEllipticCurveGroup + ) + throws + { + try self.init(copying: other._basePoint, on: group) + } + + fileprivate init(_pointAtInfinityOn group: BoringSSLEllipticCurveGroup) throws { + self._basePoint = try group.withUnsafeGroupPointer { groupPtr in + guard let pointPtr = CCryptoBoringSSL_EC_POINT_new(groupPtr) else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + return pointPtr + } + } + + fileprivate init(_generatorOf groupPtr: OpaquePointer) throws { + guard + let generatorPtr = CCryptoBoringSSL_EC_GROUP_get0_generator(groupPtr), + let pointPtr = CCryptoBoringSSL_EC_POINT_dup(generatorPtr, groupPtr) + else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + self._basePoint = pointPtr + } + + fileprivate convenience init( + multiplying scalar: ArbitraryPrecisionInteger, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws { + try self.init(_pointAtInfinityOn: group) + try group.withUnsafeGroupPointer { groupPtr in + try scalar.withUnsafeBignumPointer { scalarPtr in + guard + CCryptoBoringSSL_EC_POINT_mul(groupPtr, self._basePoint, scalarPtr, nil, nil, context?.bnCtx) + == 1 + else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + } + } + } + + deinit { + CCryptoBoringSSL_EC_POINT_free(self._basePoint) + } + + fileprivate func multiply( + by rhs: ArbitraryPrecisionInteger, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws { + try self.withPointPointer { selfPtr in + try rhs.withUnsafeBignumPointer { rhsPtr in + try group.withUnsafeGroupPointer { groupPtr in + guard + CCryptoBoringSSL_EC_POINT_mul(groupPtr, selfPtr, nil, selfPtr, rhsPtr, context?.bnCtx) != 0 + else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + } + } + } + } + + fileprivate func add( + _ rhs: EllipticCurvePoint, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws { + try self.withPointPointer { selfPtr in + try group.withUnsafeGroupPointer { groupPtr in + try rhs.withPointPointer { rhsPtr in + guard CCryptoBoringSSL_EC_POINT_add(groupPtr, selfPtr, selfPtr, rhsPtr, context?.bnCtx) != 0 + else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + } + } + } + } + + internal func invert(on group: BoringSSLEllipticCurveGroup, context: FiniteFieldArithmeticContext? = nil) throws + { + try self.withPointPointer { selfPtr in + try group.withUnsafeGroupPointer { groupPtr in + guard CCryptoBoringSSL_EC_POINT_invert(groupPtr, selfPtr, context?.bnCtx) != 0 else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + } + } + } + + fileprivate convenience init( + hashing msg: MessageBytes, + to group: BoringSSLEllipticCurveGroup, + domainSeparationTag: DSTBytes + ) throws { + let hashToCurveFunction = + switch group.curveName { + case .p256: CCryptoBoringSSLShims_EC_hash_to_curve_p256_xmd_sha256_sswu + case .p384: CCryptoBoringSSLShims_EC_hash_to_curve_p384_xmd_sha384_sswu + // BoringSSL has no P521 hash_to_curve API. + case .p521: throw CryptoBoringWrapperError.invalidParameter + case .none: throw CryptoBoringWrapperError.internalBoringSSLError() + } + + try self.init(_pointAtInfinityOn: group) + try msg.withUnsafeBytes { msgPtr in + try group.withUnsafeGroupPointer { groupPtr in + try domainSeparationTag.withUnsafeBytes { dstPtr in + guard + hashToCurveFunction( + groupPtr, + self._basePoint, + dstPtr.baseAddress, + dstPtr.count, + msgPtr.baseAddress, + msgPtr.count + ) == 1 + else { throw CryptoBoringWrapperError.internalBoringSSLError() } + } + } + } + } + + fileprivate func isEqual( + to rhs: EllipticCurvePoint, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) -> Bool { + self.withPointPointer { selfPtr in + group.withUnsafeGroupPointer { groupPtr in + rhs.withPointPointer { rhsPtr in + switch CCryptoBoringSSL_EC_POINT_cmp(groupPtr, selfPtr, rhsPtr, context?.bnCtx) { + case 0: return true + case 1: return false + default: + // EC_POINT_cmp returns an error when comparing points on different groups. + // We treat that as not equal, so we'll just clear the error and return false. + CCryptoBoringSSL_ERR_clear_error() + return false + } + } + } + } + } + + fileprivate convenience init( + x962Representation bytes: Bytes, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws { + try self.init(_pointAtInfinityOn: group) + guard + group.withUnsafeGroupPointer({ groupPtr in + bytes.withUnsafeBytes { dataPtr in + CCryptoBoringSSL_EC_POINT_oct2point( + groupPtr, + self._basePoint, + dataPtr.baseAddress, + dataPtr.count, + context?.bnCtx + ) + } + }) == 1 + else { + throw CryptoBoringWrapperError.invalidParameter + } + } + + private func x962RepresentationByteCount( + compressed: Bool, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> Int { + let numBytesNeeded = group.withUnsafeGroupPointer { groupPtr in + CCryptoBoringSSL_EC_POINT_point2oct( groupPtr, self._basePoint, compressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED, - bufPtr.baseAddress, - numBytesNeeded, + nil, + 0, context?.bnCtx ) } + guard numBytesNeeded != 0 else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + return numBytesNeeded } - guard numBytesWritten == numBytesNeeded else { - throw CryptoBoringWrapperError.internalBoringSSLError() - } - return buf + fileprivate func x962Representation( + compressed: Bool, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> Data { + let numBytesNeeded = try self.x962RepresentationByteCount( + compressed: compressed, + on: group, + context: context + ) + + var buf = Data(repeating: 0, count: numBytesNeeded) + + let numBytesWritten = group.withUnsafeGroupPointer { groupPtr in + buf.withUnsafeMutableBytes { bufPtr in + CCryptoBoringSSLShims_EC_POINT_point2oct( + groupPtr, + self._basePoint, + compressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED, + bufPtr.baseAddress, + numBytesNeeded, + context?.bnCtx + ) + } + } + guard numBytesWritten == numBytesNeeded else { + throw CryptoBoringWrapperError.internalBoringSSLError() + } + + return buf + } } } // MARK: - Helpers @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension EllipticCurvePoint { +extension EllipticCurvePoint.Backing { @inlinable package func withPointPointer(_ body: (OpaquePointer) throws -> T) rethrows -> T { try body(self._basePoint) } - @usableFromInline - package func affineCoordinates( + fileprivate func affineCoordinates( group: BoringSSLEllipticCurveGroup ) throws -> ( x: ArbitraryPrecisionInteger, y: ArbitraryPrecisionInteger @@ -440,3 +537,20 @@ extension EllipticCurvePoint { return (x: x, y: y) } } + +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) +extension EllipticCurvePoint { + @inlinable + package func withPointPointer(_ body: (OpaquePointer) throws -> T) rethrows -> T { + try self.backing.withPointPointer(body) + } + + @usableFromInline + package func affineCoordinates( + group: BoringSSLEllipticCurveGroup + ) throws -> ( + x: ArbitraryPrecisionInteger, y: ArbitraryPrecisionInteger + ) { + try self.backing.affineCoordinates(group: group) + } +} diff --git a/Sources/CryptoBoringWrapper/Util/ArbitraryPrecisionInteger.swift b/Sources/CryptoBoringWrapper/Util/ArbitraryPrecisionInteger.swift index 41f53a9fb..e0eee9fff 100644 --- a/Sources/CryptoBoringWrapper/Util/ArbitraryPrecisionInteger.swift +++ b/Sources/CryptoBoringWrapper/Util/ArbitraryPrecisionInteger.swift @@ -22,7 +22,7 @@ import Foundation /// and that provides better Swift types for this object. @usableFromInline @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -package struct ArbitraryPrecisionInteger { +package struct ArbitraryPrecisionInteger: @unchecked Sendable { private var _backing: BackingStorage @usableFromInline diff --git a/Tests/CryptoBoringWrapperTests/EllipticCurvePointTests.swift b/Tests/CryptoBoringWrapperTests/EllipticCurvePointTests.swift new file mode 100644 index 000000000..4c08fd9a9 --- /dev/null +++ b/Tests/CryptoBoringWrapperTests/EllipticCurvePointTests.swift @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import CryptoBoringWrapper +import XCTest + +final class EllipticCurvePointTests: XCTestCase { + static let p256 = try! BoringSSLEllipticCurveGroup(.p256) + + func testRepeatedMultiplyHasValueSemantics() throws { + let point = Self.p256.generator + var copy = point + try copy.multiply(by: 2, on: Self.p256) + try copy.multiply(by: 2, on: Self.p256) + + XCTAssertTrue(!copy.isEqual(to: point, on: Self.p256)) + XCTAssertTrue(try copy.isEqual(to: point.multiplying(by: 4, on: Self.p256), on: Self.p256)) + } + + func testAddHasValueSemantics() throws { + let point = Self.p256.generator + var other = point + try other.add(point, on: Self.p256) + + XCTAssertTrue(!other.isEqual(to: point, on: Self.p256)) + XCTAssertTrue(try other.isEqual(to: point.adding(point, on: Self.p256), on: Self.p256)) + } + + func testInvertingHasValueSemantics() throws { + let point = try Self.p256.generator.multiplying( + by: 2, + on: Self.p256 + ) + var other = point + try other.invert(on: Self.p256) + + XCTAssertTrue(!other.isEqual(to: point, on: Self.p256)) + XCTAssertTrue(try other.isEqual(to: point.inverting(on: Self.p256), on: Self.p256)) + } + + func testSubtractHasValueSemantics() throws { + let point = Self.p256.generator + var other = point + try other.subtract(point, on: Self.p256) + + XCTAssertTrue(!other.isEqual(to: point, on: Self.p256)) + XCTAssertTrue(try other.isEqual(to: point.subtracting(point, on: Self.p256), on: Self.p256)) + } +} From 62144264081bb8cd954cc5c5925c4ec8898d13c7 Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Thu, 26 Jun 2025 11:46:12 +0100 Subject: [PATCH 03/36] Add static SDK CI workflow (#340) Add static SDK CI workflow which runs on commits to PRs, merges to main and daily on main. --------- Co-authored-by: Cory Benfield --- .github/workflows/main.yml | 4 ++++ .github/workflows/pull_request.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 96601fa06..81d0a9dd0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,6 +21,10 @@ jobs: name: Cxx interop uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main + static-sdk: + name: Static SDK + uses: apple/swift-nio/.github/workflows/static_sdk.yml@main + macos-tests: name: macOS tests uses: apple/swift-nio/.github/workflows/macos_tests.yml@main diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 19600e3a7..4496559bd 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -56,3 +56,7 @@ jobs: with: runner_pool: general build_scheme: swift-crypto-Package + + static-sdk: + name: Static SDK + uses: apple/swift-nio/.github/workflows/static_sdk.yml@main From 74167641f874e06616eb5e46a0f69077734c0776 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Fri, 27 Jun 2025 09:01:37 +0100 Subject: [PATCH 04/36] Enable Windows CI on main (#371) This PR enables Windows CI on `main`, as well as on PRs. --- .github/workflows/main.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 81d0a9dd0..d06fb81f5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,6 +16,14 @@ jobs: linux_6_1_arguments_override: "--explicit-target-dependency-import-check error" linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" + windows_6_0_enabled: true + windows_6_1_enabled: true + windows_nightly_next_enabled: true + windows_nightly_main_enabled: true + windows_6_0_arguments_override: "--explicit-target-dependency-import-check error" + windows_6_1_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" + windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" cxx-interop: name: Cxx interop From 4ce1b9b001461593b462dce4620fdcf2a70d2fbd Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 2 Jul 2025 02:06:02 +0100 Subject: [PATCH 05/36] Add a PKCS#8 DER property to private keys (#372) ### Motivation PKCS#8 is pretty widely used. Currently getting a key in PKCS#8 DER representations requires going through a PKCS8 PEM document and then get its DER bytes. ### Modifications Add a computed property to RSA private keys that calls into BoringSSL or Security.framework to get the PKCS8 DER representation of the key. ECDH keys use the existing `derRepresentation` property to provide a property of the same name. A small ASN1 encoder adds the functionality to ed25519/x25519 keys. ### Result The representation can be accessed directly. *The identifiers for MLKEM are [still a draft](https://datatracker.ietf.org/doc/draft-ietf-lamps-kyber-certificates/). As such MLKEM is not included in the PR.* --------- Co-authored-by: Cory Benfield --- Sources/_CryptoExtras/CMakeLists.txt | 4 + .../_CryptoExtras/EC/ObjectIdentifier.swift | 37 ++++ .../EC/PKCS8DERRepresentation.swift | 76 +++++++ .../_CryptoExtras/EC/PKCS8PrivateKey.swift | 93 ++++++++ .../EC/RFC8410AlgorithmIdentifier.swift | 74 +++++++ Sources/_CryptoExtras/RSA/RSA.swift | 5 + Sources/_CryptoExtras/RSA/RSA_boring.swift | 13 ++ Sources/_CryptoExtras/RSA/RSA_security.swift | 6 + .../PKCS8DERRepresentationTests.swift | 201 ++++++++++++++++++ 9 files changed, 509 insertions(+) create mode 100644 Sources/_CryptoExtras/EC/ObjectIdentifier.swift create mode 100644 Sources/_CryptoExtras/EC/PKCS8DERRepresentation.swift create mode 100644 Sources/_CryptoExtras/EC/PKCS8PrivateKey.swift create mode 100644 Sources/_CryptoExtras/EC/RFC8410AlgorithmIdentifier.swift create mode 100644 Tests/_CryptoExtrasTests/PKCS8DERRepresentationTests.swift diff --git a/Sources/_CryptoExtras/CMakeLists.txt b/Sources/_CryptoExtras/CMakeLists.txt index 6582d439b..32445c1fa 100644 --- a/Sources/_CryptoExtras/CMakeLists.txt +++ b/Sources/_CryptoExtras/CMakeLists.txt @@ -32,6 +32,10 @@ add_library(_CryptoExtras "ARC/ARCServer.swift" "ChaCha20CTR/BoringSSL/ChaCha20CTR_boring.swift" "ChaCha20CTR/ChaCha20CTR.swift" + "EC/ObjectIdentifier.swift" + "EC/PKCS8DERRepresentation.swift" + "EC/PKCS8PrivateKey.swift" + "EC/RFC8410AlgorithmIdentifier.swift" "ECToolbox/BoringSSL/ECToolbox_boring.swift" "ECToolbox/ECToolbox.swift" "H2G/HashToField.swift" diff --git a/Sources/_CryptoExtras/EC/ObjectIdentifier.swift b/Sources/_CryptoExtras/EC/ObjectIdentifier.swift new file mode 100644 index 000000000..87c79f531 --- /dev/null +++ b/Sources/_CryptoExtras/EC/ObjectIdentifier.swift @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftASN1 + +extension ASN1ObjectIdentifier.AlgorithmIdentifier { + // Identifies the key agreement algorithm X25519. + // + // This identifier is defined in RFC 8410 + static let idX25519: ASN1ObjectIdentifier = [1, 3, 101, 110] + + // Identifies the key agreement algorithm X448. + // + // This identifier is defined in RFC 8410 + static let idX448: ASN1ObjectIdentifier = [1, 3, 101, 111] + + // Identifies the signature algorithm Ed25519. + // + // This identifier is defined in RFC 8410 + static let idEd25519: ASN1ObjectIdentifier = [1, 3, 101, 112] + + // Identifies the signature algorithm Ed448. + // + // This identifier is defined in RFC 8410 + static let idEd448: ASN1ObjectIdentifier = [1, 3, 101, 113] +} diff --git a/Sources/_CryptoExtras/EC/PKCS8DERRepresentation.swift b/Sources/_CryptoExtras/EC/PKCS8DERRepresentation.swift new file mode 100644 index 000000000..a3449ca64 --- /dev/null +++ b/Sources/_CryptoExtras/EC/PKCS8DERRepresentation.swift @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Crypto +import Foundation +import SwiftASN1 + +@available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *) +extension Curve25519.Signing.PrivateKey { + /// A Distinguished Encoding Rules (DER) encoded representation of the private key in PKCS#8 format. + public var pkcs8DERRepresentation: Data { + let pkey = ASN1.PKCS8PrivateKey(algorithm: .ed25519, privateKey: Array(self.rawRepresentation)) + var serializer = DER.Serializer() + + // Serializing this key can't throw + try! serializer.serialize(pkey) + return Data(serializer.serializedBytes) + } +} + +@available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *) +extension Curve25519.KeyAgreement.PrivateKey { + /// A Distinguished Encoding Rules (DER) encoded representation of the private key in PKCS#8 format. + public var pkcs8DERRepresentation: Data { + let pkey = ASN1.PKCS8PrivateKey(algorithm: .x25519, privateKey: Array(self.rawRepresentation)) + var serializer = DER.Serializer() + + // Serializing this key can't throw + try! serializer.serialize(pkey) + return Data(serializer.serializedBytes) + } +} + +@available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *) +extension P256.Signing.PrivateKey { + /// A Distinguished Encoding Rules (DER) encoded representation of the private key in PKCS#8 format. + /// + /// This property provides the same output as the existing `derRepresentation` property, + /// which already conforms to the PKCS#8 standard. + public var pkcs8DERRepresentation: Data { + self.derRepresentation + } +} + +@available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *) +extension P384.Signing.PrivateKey { + /// A Distinguished Encoding Rules (DER) encoded representation of the private key in PKCS#8 format. + /// + /// This property provides the same output as the existing `derRepresentation` property, + /// which already conforms to the PKCS#8 standard. + public var pkcs8DERRepresentation: Data { + self.derRepresentation + } +} + +@available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *) +extension P521.Signing.PrivateKey { + /// A Distinguished Encoding Rules (DER) encoded representation of the private key in PKCS#8 format. + /// + /// This property provides the same output as the existing `derRepresentation` property, + /// which already conforms to the PKCS#8 standard. + public var pkcs8DERRepresentation: Data { + self.derRepresentation + } +} diff --git a/Sources/_CryptoExtras/EC/PKCS8PrivateKey.swift b/Sources/_CryptoExtras/EC/PKCS8PrivateKey.swift new file mode 100644 index 000000000..5de7a11e4 --- /dev/null +++ b/Sources/_CryptoExtras/EC/PKCS8PrivateKey.swift @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Crypto +import SwiftASN1 + +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) +extension ASN1 { + // A PKCS#8 private key is one of two formats, depending on the version: + // + // For PKCS#8 we need the following for the private key: + // + // PrivateKeyInfo ::= SEQUENCE { + // version Version, + // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + // privateKey PrivateKey, + // attributes [0] IMPLICIT Attributes OPTIONAL } + // + // Version ::= INTEGER + // + // PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + // + // PrivateKey ::= OCTET STRING + // + // Attributes ::= SET OF Attribute + // + // We disregard the attributes because we don't support them anyway. + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) + struct PKCS8PrivateKey: DERImplicitlyTaggable { + static var defaultIdentifier: ASN1Identifier { + .sequence + } + + var algorithm: RFC8410AlgorithmIdentifier + + var privateKey: ASN1OctetString + + init(derEncoded rootNode: ASN1Node, withIdentifier identifier: ASN1Identifier) throws { + self = try DER.sequence(rootNode, identifier: identifier) { nodes in + let version = try Int(derEncoded: &nodes) + guard version == 0 || version == 1 else { + throw ASN1Error.invalidASN1Object(reason: "Version number mismatch") + } + + let algorithm = try ASN1.RFC8410AlgorithmIdentifier(derEncoded: &nodes) + let privateKeyBytes = try ASN1OctetString(derEncoded: &nodes) + + // We ignore the attributes + _ = try DER.optionalExplicitlyTagged(&nodes, tagNumber: 0, tagClass: .contextSpecific) { _ in } + + let privateKeyNode = try DER.parse(privateKeyBytes.bytes) + let privateKey = try ASN1OctetString(derEncoded: privateKeyNode) + + return try .init(algorithm: algorithm, privateKey: privateKey) + } + } + + private init(algorithm: ASN1.RFC8410AlgorithmIdentifier, privateKey: ASN1OctetString) throws { + self.privateKey = privateKey + self.algorithm = algorithm + } + + init(algorithm: ASN1.RFC8410AlgorithmIdentifier, privateKey: [UInt8]) { + self.algorithm = algorithm + self.privateKey = ASN1OctetString(contentBytes: privateKey[...]) + } + + func serialize(into coder: inout DER.Serializer, withIdentifier identifier: ASN1Identifier) throws { + try coder.appendConstructedNode(identifier: identifier) { coder in + try coder.serialize(0) + try coder.serialize(self.algorithm) + + // Here's a weird one: we recursively serialize the private key, and then turn the bytes into an octet string. + var subCoder = DER.Serializer() + try subCoder.serialize(self.privateKey) + let serializedKey = ASN1OctetString(contentBytes: subCoder.serializedBytes[...]) + + try coder.serialize(serializedKey) + } + } + } +} diff --git a/Sources/_CryptoExtras/EC/RFC8410AlgorithmIdentifier.swift b/Sources/_CryptoExtras/EC/RFC8410AlgorithmIdentifier.swift new file mode 100644 index 000000000..b73b4373e --- /dev/null +++ b/Sources/_CryptoExtras/EC/RFC8410AlgorithmIdentifier.swift @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftASN1 + +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) +extension ASN1 { + @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) + struct RFC8410AlgorithmIdentifier: DERImplicitlyTaggable, Hashable { + static var defaultIdentifier: ASN1Identifier { + .sequence + } + + var algorithm: ASN1ObjectIdentifier + + // RFC 8410: For all of these OIDs, the parameters MUST be absent. + // They are still part of the identifer block. + var parameters: ASN1Any? + + init(algorithm: ASN1ObjectIdentifier, parameters: ASN1Any?) { + self.algorithm = algorithm + self.parameters = parameters + } + + init(derEncoded rootNode: ASN1Node, withIdentifier identifier: ASN1Identifier) throws { + // The AlgorithmIdentifier block looks like this. + // + // AlgorithmIdentifier ::= SEQUENCE { + // algorithm OBJECT IDENTIFIER, + // parameters ANY DEFINED BY algorithm OPTIONAL + // } + // + // We don't bother with helpers: we just try to decode it directly. + self = try DER.sequence(rootNode, identifier: identifier) { nodes in + let algorithmOID = try ASN1ObjectIdentifier(berEncoded: &nodes) + + let parameters = nodes.next().map { ASN1Any(berEncoded: $0) } + + return .init(algorithm: algorithmOID, parameters: parameters) + } + } + + func serialize(into coder: inout DER.Serializer, withIdentifier identifier: ASN1Identifier) throws { + try coder.appendConstructedNode(identifier: identifier) { coder in + try coder.serialize(self.algorithm) + if let parameters = self.parameters { + try coder.serialize(parameters) + } + } + } + } +} + +@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) +extension ASN1.RFC8410AlgorithmIdentifier { + static let x25519 = ASN1.RFC8410AlgorithmIdentifier(algorithm: .AlgorithmIdentifier.idX25519, parameters: nil) + + static let x448 = ASN1.RFC8410AlgorithmIdentifier(algorithm: .AlgorithmIdentifier.idX448, parameters: nil) + + static let ed25519 = ASN1.RFC8410AlgorithmIdentifier(algorithm: .AlgorithmIdentifier.idEd25519, parameters: nil) + + static let ed448 = ASN1.RFC8410AlgorithmIdentifier(algorithm: .AlgorithmIdentifier.idEd448, parameters: nil) +} diff --git a/Sources/_CryptoExtras/RSA/RSA.swift b/Sources/_CryptoExtras/RSA/RSA.swift index c0acdbb4a..a805097f2 100644 --- a/Sources/_CryptoExtras/RSA/RSA.swift +++ b/Sources/_CryptoExtras/RSA/RSA.swift @@ -259,6 +259,11 @@ extension _RSA.Signing { self.backing.pemRepresentation } + /// A Distinguished Encoding Rules (DER) encoded representation of the private key in PKCS#8 format. + public var pkcs8DERRepresentation: Data { + self.backing.pkcs8DERRepresentation + } + public var pkcs8PEMRepresentation: String { self.backing.pkcs8PEMRepresentation } diff --git a/Sources/_CryptoExtras/RSA/RSA_boring.swift b/Sources/_CryptoExtras/RSA/RSA_boring.swift index cd560d759..3c6eebbb7 100644 --- a/Sources/_CryptoExtras/RSA/RSA_boring.swift +++ b/Sources/_CryptoExtras/RSA/RSA_boring.swift @@ -106,6 +106,10 @@ internal struct BoringSSLRSAPrivateKey: Sendable { self.backing.pemRepresentation } + var pkcs8DERRepresentation: Data { + self.backing.pkcs8DERRepresentation + } + var pkcs8PEMRepresentation: String { self.backing.pkcs8PEMRepresentation } @@ -737,6 +741,15 @@ extension BoringSSLRSAPrivateKey { } } + fileprivate var pkcs8DERRepresentation: Data { + BIOHelper.withWritableMemoryBIO { bio in + let rc = CCryptoBoringSSL_i2d_PKCS8PrivateKeyInfo_bio(bio, self.pointer) + precondition(rc == 1, "Exporting PKCS8 DER key failed") + + return try! Data(copyingMemoryBIO: bio) + } + } + fileprivate var pkcs8PEMRepresentation: String { BIOHelper.withWritableMemoryBIO { bio in let evp = CCryptoBoringSSL_EVP_PKEY_new() diff --git a/Sources/_CryptoExtras/RSA/RSA_security.swift b/Sources/_CryptoExtras/RSA/RSA_security.swift index 0a88fcc6a..31708a38f 100644 --- a/Sources/_CryptoExtras/RSA/RSA_security.swift +++ b/Sources/_CryptoExtras/RSA/RSA_security.swift @@ -169,6 +169,12 @@ internal struct SecurityRSAPrivateKey: @unchecked Sendable { return pemString.appending("\n") } + var pkcs8DERRepresentation: Data { + let pkcs1Bytes = self.derRepresentation + let pkcs8Bytes = Data(privateKeyPKCS8BytesForPKCS1Bytes: pkcs1Bytes) + return pkcs8Bytes + } + var keySizeInBits: Int { SecKeyGetBlockSize(self.backing) * 8 } diff --git a/Tests/_CryptoExtrasTests/PKCS8DERRepresentationTests.swift b/Tests/_CryptoExtrasTests/PKCS8DERRepresentationTests.swift new file mode 100644 index 000000000..1cc754c2d --- /dev/null +++ b/Tests/_CryptoExtrasTests/PKCS8DERRepresentationTests.swift @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Crypto +import Foundation +import XCTest + +@testable import _CryptoExtras + +final class PKCS8DERRepresentationTests: XCTestCase { + func test_RSA() { + let rsaPrivateKeyPEM = """ + -----BEGIN RSA PRIVATE KEY----- + MIIEpQIBAAKCAQEAxeBrlW1i+gXmqC/4XlTppLCXPpksZbxsc0AufsWzpcIxBAQL + jr4LxXyOenZcyhrdXxksEsCJE/8stJuUZgiFyDMesWjoL5bYyOpWrwPyvCMNaC8F + 15cKe5n7OSVNU312X0ZSxTZAOrCEH0kGrsXoQn5JgHygVXejSPlHw8F1Pwps3pnc + cRYE9vsHZegspUI3DaqWgmewFWz6jSMY0v1DcZv2Xw+pMLeXEpKKMf+eo90mHShh + n8FijsI1tFuYD++LmM/e1TV1z+W2sPL2CaosBO890WeCyL/bFl4j1lmdnXdBNX+l + ub/5HTqI7hxAm/qonzDs3iV5KK1ZWZTVsPyqtwIDAQABAoIBAQCGLBQG8HMKgXHT + XSOWIxGCIFONmKMoIMmQpFZik3+qx7AgvvVvRqIIuNqLYzKrv+eXEiR2WqMYMhCI + Lm5DeUftZexL84xsqGY6Zdt9NLoko8f1et0FQF9VTCWyq/5wvEPFepOpMY3/vaz4 + 4bVsULmaTLNeMiMtkL/hPVZSAB2WLjI7EgOq7JamRBCMY+ivtdtqi12kO8vaA2Ns + dSKuU+e8tvAP4o6cMvuLtcqLy2UeoZzYTI998up0tqn+mGHl0DHx6MSi/TbVv3v8 + gSQGlBvWzUx85vz+1GyjRn+o4hO/tibtP6aKfWYztIyLgkaU8JuDZzT+CwwmCnEH + ge/JmGuRAoGBAPypZ9MuWi1Ms57nVcpHRSHUc+cO/CfoaC4kRzgh99ApDbL+rj78 + 9eXkS10Z8hTLQprcznQr+WZhnhNw13PrvzaGhtOXd/xLBnWlqZ6aIGYrJgKu+JLl + yGVBZByG70yXel8IZt9l4CYctlS4D8iYAtdR+CCn8XGrc8JILnwBbYDNAoGBAMh9 + tiC8hyIc/wBV/WcgtpY6tPkrN4uw6WREH+UkVpvNM2kMMCgn1YLHbYq1vSKN3rKZ + L9Ep4+8umRMg5yTgq9iURMoNjq+qU8NDF0nRljmyJRvgA5Ez2iQErm3y5dYxK+8w + BRvCkDeOiiu1Mnd9chgu0tQhpfo7o+T3XeXB5omTAoGBAKl3IqlVnKxnls6NEVC0 + Tt0q93ZR6bUGv+G6+X3f4qxe7M5S3iJnXrMMVbQjc+iYkJr4YQ0wdX5DGVimxgv9 + Ymo6/vGq1ZKF69Y7ADLd479DT6JbI2S79JZdrr0nkBfKPgzBwOY0GYzWk0Dtl8CO + nNE5LHkSy/HW8rSr32nTN1Q9AoGAOdl8GcoMO92d/pzRN1aLGKHr4hGEP3xWe6Xk + hhuMGfyFnwPzSULlKo0coG98GWJSJbppv7KUoEkTxh8yUsO5Eg8GIj7zMuC0tpy/ + NX+SFye96WMj5FvPz6DCK9twUfNyN9vlPXNQZZdtatsnqq65oxyvnKHw4FkhG0n8 + //SI7p0CgYEA9CoA6/3rRIVKKEOgeCQHDVKIJIauTUskwdrBHLVU7SH+cfQ6VNy6 + zp/M54MpUP5jviSL61HmRoEqqcMWLALJHyZ1yQAZXSpthyMw0ahqTUZ71j1ukIO0 + UUjK3drJJd2jGQ0LfhlDCX7VmURIqJ6kaQ0WBNAJLFhTW4AS8HGYRZk= + -----END RSA PRIVATE KEY----- + """ + + // Same key in PKCS8 DER representation. + let encodedPKCS8DER = + "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDF4GuVbWL6BeaoL/heVOmksJc+mSxlvGxzQC5+xbOlwjEEBAuOvgvFfI56dlzKGt1fGSwSwIkT/yy0m5RmCIXIMx6xaOgvltjI6lavA/K8Iw1oLwXXlwp7mfs5JU1TfXZfRlLFNkA6sIQfSQauxehCfkmAfKBVd6NI+UfDwXU/CmzemdxxFgT2+wdl6CylQjcNqpaCZ7AVbPqNIxjS/UNxm/ZfD6kwt5cSkoox/56j3SYdKGGfwWKOwjW0W5gP74uYz97VNXXP5baw8vYJqiwE7z3RZ4LIv9sWXiPWWZ2dd0E1f6W5v/kdOojuHECb+qifMOzeJXkorVlZlNWw/Kq3AgMBAAECggEBAIYsFAbwcwqBcdNdI5YjEYIgU42YoyggyZCkVmKTf6rHsCC+9W9Gogi42otjMqu/55cSJHZaoxgyEIgubkN5R+1l7EvzjGyoZjpl2300uiSjx/V63QVAX1VMJbKr/nC8Q8V6k6kxjf+9rPjhtWxQuZpMs14yIy2Qv+E9VlIAHZYuMjsSA6rslqZEEIxj6K+122qLXaQ7y9oDY2x1Iq5T57y28A/ijpwy+4u1yovLZR6hnNhMj33y6nS2qf6YYeXQMfHoxKL9NtW/e/yBJAaUG9bNTHzm/P7UbKNGf6jiE7+2Ju0/pop9ZjO0jIuCRpTwm4NnNP4LDCYKcQeB78mYa5ECgYEA/Kln0y5aLUyznudVykdFIdRz5w78J+hoLiRHOCH30CkNsv6uPvz15eRLXRnyFMtCmtzOdCv5ZmGeE3DXc+u/NoaG05d3/EsGdaWpnpogZismAq74kuXIZUFkHIbvTJd6Xwhm32XgJhy2VLgPyJgC11H4IKfxcatzwkgufAFtgM0CgYEAyH22ILyHIhz/AFX9ZyC2ljq0+Ss3i7DpZEQf5SRWm80zaQwwKCfVgsdtirW9Io3espkv0Snj7y6ZEyDnJOCr2JREyg2Or6pTw0MXSdGWObIlG+ADkTPaJASubfLl1jEr7zAFG8KQN46KK7Uyd31yGC7S1CGl+juj5Pdd5cHmiZMCgYEAqXciqVWcrGeWzo0RULRO3Sr3dlHptQa/4br5fd/irF7szlLeImdeswxVtCNz6JiQmvhhDTB1fkMZWKbGC/1iajr+8arVkoXr1jsAMt3jv0NPolsjZLv0ll2uvSeQF8o+DMHA5jQZjNaTQO2XwI6c0TkseRLL8dbytKvfadM3VD0CgYA52XwZygw73Z3+nNE3VosYoeviEYQ/fFZ7peSGG4wZ/IWfA/NJQuUqjRygb3wZYlIlumm/spSgSRPGHzJSw7kSDwYiPvMy4LS2nL81f5IXJ73pYyPkW8/PoMIr23BR83I32+U9c1Bll21q2yeqrrmjHK+cofDgWSEbSfz/9IjunQKBgQD0KgDr/etEhUooQ6B4JAcNUogkhq5NSyTB2sEctVTtIf5x9DpU3LrOn8zngylQ/mO+JIvrUeZGgSqpwxYsAskfJnXJABldKm2HIzDRqGpNRnvWPW6Qg7RRSMrd2skl3aMZDQt+GUMJftWZREionqRpDRYE0AksWFNbgBLwcZhFmQ==" + let rsaPrivateKeyPKCS8DER = Data(base64Encoded: encodedPKCS8DER)! + + // Create private keys from both representations of the same key + let keyFromPEM = try! _RSA.Signing.PrivateKey(pemRepresentation: rsaPrivateKeyPEM) + let keyFromDER = try! _RSA.Signing.PrivateKey(derRepresentation: rsaPrivateKeyPKCS8DER) + + XCTAssertEqual(keyFromDER.keySizeInBits, 2048) + XCTAssertEqual(keyFromPEM.keySizeInBits, 2048) + + // The keys match + XCTAssertEqual(keyFromPEM.derRepresentation, keyFromDER.derRepresentation) + + // Our property creates the expected representation + XCTAssertEqual(keyFromPEM.pkcs8DERRepresentation, rsaPrivateKeyPKCS8DER) + } + + func test_ed25519() { + let privateKeyPEM = """ + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIFSrpkDrDWBMoz/YWjFaW9t4TQaKWyalZ6TRDUS/4+LE + -----END PRIVATE KEY----- + """ + + // Same key in PKCS8 DER representation. + let privateKeyPKCS8DER = Data( + base64Encoded: + "MC4CAQAwBQYDK2VwBCIEIFSrpkDrDWBMoz/YWjFaW9t4TQaKWyalZ6TRDUS/4+LE" + )! + + // We only need the 32 bytes of the key. + let document = try! ASN1.PEMDocument(pemString: privateKeyPEM) + var bytes = document.derBytes + bytes.removeFirst(bytes.count - 32) + + let keyFromDER = try! Curve25519.Signing.PrivateKey(rawRepresentation: bytes) + + let pkcs8 = keyFromDER.pkcs8DERRepresentation + + XCTAssertEqual(pkcs8, privateKeyPKCS8DER) + } + + func test_ed25519_rfc_example() { + // Example key from RFC 8410, Section 10.3. + // Create private key from bytes. + let keyBytes = Data( + base64Encoded: + "1O5y2/kTWErVttjx92n4rTr+fCjL8dT74Jeoj0R1WEI=" + )! + // Same key in PKCS8 DER representation. + let exampleKeyPKCS8DER = Data( + base64Encoded: + "MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC" + )! + + // Create key from the private key bytes and compare our exported representation. + let exampleKey = try! Curve25519.Signing.PrivateKey(rawRepresentation: keyBytes) + + XCTAssertEqual(exampleKey.pkcs8DERRepresentation, exampleKeyPKCS8DER) + } + + func test_x25519() { + let privateKeyPEM = """ + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VuBCIEIKBtrFwBvmRtGZjMyj0rXewOQclz/8cdEY981glA/w5a + -----END PRIVATE KEY----- + """ + + // Same key in PKCS8 DER representation. + let privateKeyPKCS8DER = Data( + base64Encoded: + "MC4CAQAwBQYDK2VuBCIEIKBtrFwBvmRtGZjMyj0rXewOQclz/8cdEY981glA/w5a" + )! + + // We only need the 32 bytes of the key. + let document = try! ASN1.PEMDocument(pemString: privateKeyPEM) + var bytes = document.derBytes + bytes.removeFirst(bytes.count - 32) + + // Create key from the private key bytes and compare our exported representation. + let keyFromDER = try! Curve25519.KeyAgreement.PrivateKey(rawRepresentation: bytes) + + XCTAssertEqual(keyFromDER.pkcs8DERRepresentation, privateKeyPKCS8DER) + } + + func test_P256() { + let privateKeyPEM = """ + -----BEGIN PRIVATE KEY----- + MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgO6fz+J/sZqbCki3h + chsrVb69KW8q24pLDwotAtwz/gahRANCAASkBqszxMCGrd8l+xZitPto300blCWk + wRCdoar3UeEEfuH5LsJ3kNjN+oMZmHAmnhHE6cqLHFem/ujsGgrqJ3E8 + -----END PRIVATE KEY----- + """ + let encodedPKCS8DER = + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgO6fz+J/sZqbCki3hchsrVb69KW8q24pLDwotAtwz/gahRANCAASkBqszxMCGrd8l+xZitPto300blCWkwRCdoar3UeEEfuH5LsJ3kNjN+oMZmHAmnhHE6cqLHFem/ujsGgrqJ3E8" + let privateKeyPKCS8DER = Data(base64Encoded: encodedPKCS8DER)! + + // Create key from PEM and compare our exported representation. + let keyFromPEM = try! P256.Signing.PrivateKey(pemRepresentation: privateKeyPEM) + + XCTAssertEqual(keyFromPEM.pkcs8DERRepresentation, privateKeyPKCS8DER) + } + + func test_P384() { + let privateKeyPEM = """ + -----BEGIN PRIVATE KEY----- + MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDD2qUnvEDviY5Hon7fx + rsJmgWCGQcNlU+nXEWOoFPC49kioBm1hsveCH0q3vk9GjZKhZANiAAQFzxvdG2gI + uWZfkAeMW2BzsKGdUWwybx8MHs8fv48MCPmfvL4kIvkU9T7F7diut41ciSzILv5/ + gb45xx6+dZjlWxIopstQuBu5v/J4oa3fgN1uYQJTSsKksDi3L52TcnY= + -----END PRIVATE KEY----- + """ + + // Same key in PKCS8 DER representation. + let encodedPKCS8DER = + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDD2qUnvEDviY5Hon7fxrsJmgWCGQcNlU+nXEWOoFPC49kioBm1hsveCH0q3vk9GjZKhZANiAAQFzxvdG2gIuWZfkAeMW2BzsKGdUWwybx8MHs8fv48MCPmfvL4kIvkU9T7F7diut41ciSzILv5/gb45xx6+dZjlWxIopstQuBu5v/J4oa3fgN1uYQJTSsKksDi3L52TcnY=" + let privateKeyPKCS8DER = Data(base64Encoded: encodedPKCS8DER)! + + // Create key from PEM and compare our exported representation. + let keyFromPEM = try! P384.Signing.PrivateKey(pemRepresentation: privateKeyPEM) + + XCTAssertEqual(keyFromPEM.pkcs8DERRepresentation, privateKeyPKCS8DER) + } + + func test_P521() { + let privateKeyPEM = """ + -----BEGIN PRIVATE KEY----- + MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBcQv0MVt8xb5teBQJ + Mqn7wnQ2GVzgL+jkMERcMaABU7+UL7uC0ff+15RKEI2RwKLVUVvp3WJigCHBDpwY + qI9OFnyhgYkDgYYABAD7PeX+GFUa99yyhYJ4WReKq2nLUOjo+ZZ+pdepc0EaESj+ + 8o2Sv4mRjIU0s3WFTNx0mh9BKiszBNRu2nq148ZfCwAcAiJu4xcwR2o+L7BqNadJ + 1hCoVItbL61BWxAMITZPegQLMV1K7SMS6NNkYBBIh10Q870tBO26VJ5wMm5K46MA + Cg== + -----END PRIVATE KEY----- + """ + + // Same key in PKCS8 DER representation. + let encodedPKCS8DER = + "MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBcQv0MVt8xb5teBQJMqn7wnQ2GVzgL+jkMERcMaABU7+UL7uC0ff+15RKEI2RwKLVUVvp3WJigCHBDpwYqI9OFnyhgYkDgYYABAD7PeX+GFUa99yyhYJ4WReKq2nLUOjo+ZZ+pdepc0EaESj+8o2Sv4mRjIU0s3WFTNx0mh9BKiszBNRu2nq148ZfCwAcAiJu4xcwR2o+L7BqNadJ1hCoVItbL61BWxAMITZPegQLMV1K7SMS6NNkYBBIh10Q870tBO26VJ5wMm5K46MACg==" + let privateKeyPKCS8DER = Data(base64Encoded: encodedPKCS8DER) + + // Create key from PEM and compare our exported representation. + let keyFromPEM = try! P521.Signing.PrivateKey(pemRepresentation: privateKeyPEM) + + XCTAssertEqual(keyFromPEM.pkcs8DERRepresentation, privateKeyPKCS8DER) + } +} From 9fb2fd8d3c0d923705d14b524838c9bc2f2fc2d0 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 2 Jul 2025 02:13:58 +0100 Subject: [PATCH 06/36] Remove security backend (#373) ### Motivation: Depending on the platform Swift Crypto Extras might use an implementation backed by `Security.framework`, specifically for RSA. Since BoringSSL is a necessary dependency on all platforms, we can deduplicate the implementation and keep a single backend. ### Modifications: Remove the `Security.framework` implementation and tie the RSA backend to BoringSSL. ### Result: Swift Crypto Extras always uses the BoringSSL backend for RSA. --------- Co-authored-by: Cory Benfield --- .swiftformatignore | 1 - Sources/_CryptoExtras/CMakeLists.txt | 1 - Sources/_CryptoExtras/RSA/RSA.swift | 39 +- Sources/_CryptoExtras/RSA/RSA_security.swift | 484 ------------------- 4 files changed, 4 insertions(+), 521 deletions(-) delete mode 100644 Sources/_CryptoExtras/RSA/RSA_security.swift diff --git a/.swiftformatignore b/.swiftformatignore index 03469d9a9..984746041 100644 --- a/.swiftformatignore +++ b/.swiftformatignore @@ -94,7 +94,6 @@ Sources/_CryptoExtras/OPRFs/VOPRFClient.swift Sources/_CryptoExtras/OPRFs/VOPRFServer.swift Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift Sources/_CryptoExtras/RSA/RSA.swift -Sources/_CryptoExtras/RSA/RSA_security.swift Sources/_CryptoExtras/Util/BoringSSLHelpers.swift Sources/_CryptoExtras/Util/DigestType.swift Sources/_CryptoExtras/Util/Error.swift diff --git a/Sources/_CryptoExtras/CMakeLists.txt b/Sources/_CryptoExtras/CMakeLists.txt index 32445c1fa..a9959d7e0 100644 --- a/Sources/_CryptoExtras/CMakeLists.txt +++ b/Sources/_CryptoExtras/CMakeLists.txt @@ -56,7 +56,6 @@ add_library(_CryptoExtras "RSA/RSA+BlindSigning.swift" "RSA/RSA.swift" "RSA/RSA_boring.swift" - "RSA/RSA_security.swift" "Util/BoringSSLHelpers.swift" "Util/CryptoKitErrors_boring.swift" "Util/Data+Extensions.swift" diff --git a/Sources/_CryptoExtras/RSA/RSA.swift b/Sources/_CryptoExtras/RSA/RSA.swift index a805097f2..642236bf9 100644 --- a/Sources/_CryptoExtras/RSA/RSA.swift +++ b/Sources/_CryptoExtras/RSA/RSA.swift @@ -16,17 +16,10 @@ import Crypto import CryptoBoringWrapper import SwiftASN1 -#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -fileprivate typealias BackingPublicKey = SecurityRSAPublicKey -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -fileprivate typealias BackingPrivateKey = SecurityRSAPrivateKey -#else @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) fileprivate typealias BackingPublicKey = BoringSSLRSAPublicKey @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) fileprivate typealias BackingPrivateKey = BoringSSLRSAPrivateKey -#endif /// Types associated with the RSA algorithm /// @@ -120,14 +113,8 @@ extension _RSA.Signing { } /// Construct an RSA public key with the specified parameters. - /// - /// Only the BoringSSL backend provides APIs to create a key from its parameters so we first create a BoringSSL - /// key, and then pass it to the platform-specific initializer that accepts a BoringSSL key. - /// - /// On Darwin platforms, this will serialize it to PEM format, and then construct a platform-specific key from - /// the PEM representation. public init(n: some ContiguousBytes, e: some ContiguousBytes) throws { - self.backing = try BackingPublicKey(BoringSSLRSAPublicKey(n: n, e: e)) + self.backing = try BackingPublicKey(n: n, e: e) } public var pkcs1DERRepresentation: Data { @@ -218,14 +205,8 @@ extension _RSA.Signing { } /// Construct an RSA private key with the specified parameters. - /// - /// Only the BoringSSL backend provides APIs to create a key from its parameters so we first create a BoringSSL - /// key, and then pass it to the platform-specific initializer that accepts a BoringSSL key. - /// - /// On Darwin platforms, this will serialize it to DER format, and then construct a platform-specific key from - /// the DER representation. public init(n: some ContiguousBytes, e: some ContiguousBytes, d: some ContiguousBytes, p: some ContiguousBytes, q: some ContiguousBytes) throws { - self.backing = try BackingPrivateKey(BoringSSLRSAPrivateKey(n: n, e: e, d: d, p: p, q: q)) + self.backing = try BackingPrivateKey(n: n, e: e, d: d, p: p, q: q) } /// Randomly generate a new RSA private key of a given size. @@ -546,14 +527,8 @@ extension _RSA.Encryption { } /// Construct an RSA public key with the specified parameters. - /// - /// Only the BoringSSL backend provides APIs to create a key from its parameters so we first create a BoringSSL - /// key, and then pass it to the platform-specific initializer that accepts a BoringSSL key. - /// - /// On Darwin platforms, this will serialize it to DER format, and then construct a platform-specific key from - /// the DER representation. public init(n: some ContiguousBytes, e: some ContiguousBytes) throws { - self.backing = try BackingPublicKey(BoringSSLRSAPublicKey(n: n, e: e)) + self.backing = try BackingPublicKey(n: n, e: e) } public var pkcs1DERRepresentation: Data { self.backing.pkcs1DERRepresentation } @@ -614,14 +589,8 @@ extension _RSA.Encryption { /// Construct an RSA private key with the specified parameters. - /// - /// Only the BoringSSL backend provides APIs to create a key from its parameters so we first create a BoringSSL - /// key, and then pass it to the platform-specific initializer that accepts a BoringSSL key. - /// - /// On Darwin platforms, this will serialize it to PEM format, and then construct a platform-specific key from - /// the PEM representation. public init(n: some ContiguousBytes, e: some ContiguousBytes, d: some ContiguousBytes, p: some ContiguousBytes, q: some ContiguousBytes) throws { - self.backing = try BackingPrivateKey(BoringSSLRSAPrivateKey(n: n, e: e, d: d, p: p, q: q)) + self.backing = try BackingPrivateKey(n: n, e: e, d: d, p: p, q: q) } /// Randomly generate a new RSA private key of a given size. diff --git a/Sources/_CryptoExtras/RSA/RSA_security.swift b/Sources/_CryptoExtras/RSA/RSA_security.swift deleted file mode 100644 index 31708a38f..000000000 --- a/Sources/_CryptoExtras/RSA/RSA_security.swift +++ /dev/null @@ -1,484 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2021 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// -import Foundation -import Crypto - -#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API -@_implementationOnly import Security - -// unchecked sendable until `SecKey` gets sendable annotations -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -internal struct SecurityRSAPublicKey: @unchecked Sendable { - private var backing: SecKey - - init(pemRepresentation: String) throws { - let document = try ASN1.PEMDocument(pemString: pemRepresentation) - self = try .init(derRepresentation: document.derBytes) - } - - init(derRepresentation: Bytes) throws { - let keyAttributes: [CFString: Any] = [ - kSecAttrKeyType: kSecAttrKeyTypeRSA, - kSecAttrKeyClass: kSecAttrKeyClassPublic, - ] - let data = Data(derRepresentation) - var error: Unmanaged? = nil - let key = SecKeyCreateWithData(data as CFData, keyAttributes as CFDictionary, &error) - - guard let unwrappedKey = key else { - // If this returns nil, error must be set. - throw error!.takeRetainedValue() as Error - } - - self.backing = unwrappedKey - } - - init(_ boringSSLKey: BoringSSLRSAPublicKey) throws { - try self.init(derRepresentation: boringSSLKey.derRepresentation) - } - - var pkcs1DERRepresentation: Data { - var error: Unmanaged? = nil - let representation = SecKeyCopyExternalRepresentation(self.backing, &error) - return representation! as Data - } - - var pkcs1PEMRepresentation: String { - return ASN1.PEMDocument(type: _RSA.PKCS1PublicKeyType, derBytes: self.pkcs1DERRepresentation).pemString - } - - var derRepresentation: Data { - return Data(spkiBytesForPKCS1Bytes: self.pkcs1DERRepresentation) - } - - var pemRepresentation: String { - return ASN1.PEMDocument(type: _RSA.SPKIPublicKeyType, derBytes: self.derRepresentation).pemString - } - - var keySizeInBits: Int { - SecKeyGetBlockSize(self.backing) * 8 - } - - fileprivate init(_ backing: SecKey) { - self.backing = backing - } - - func getKeyPrimitives() throws -> (n: Data, e: Data) { - try BoringSSLRSAPublicKey(derRepresentation: self.derRepresentation).getKeyPrimitives() - } -} - -// unchecked sendable until `SecKey` gets sendable annotations -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -internal struct SecurityRSAPrivateKey: @unchecked Sendable { - private var backing: SecKey - - init(pemRepresentation: String) throws { - let document = try ASN1.PEMDocument(pemString: pemRepresentation) - - switch document.type { - case _RSA.PKCS1KeyType: - // This is what is expected by Security.framework - self = try .init(derRepresentation: document.derBytes) - case _RSA.PKCS8KeyType: - guard let pkcs8Bytes = document.derBytes.pkcs8RSAKeyBytes else { - throw _CryptoRSAError.invalidPEMDocument - } - self = try .init(derRepresentation: pkcs8Bytes) - default: - throw _CryptoRSAError.invalidPEMDocument - } - - } - - init(derRepresentation: Bytes) throws { - let keyAttributes: [CFString: Any] = [ - kSecAttrKeyType: kSecAttrKeyTypeRSA, - kSecAttrKeyClass: kSecAttrKeyClassPrivate, - ] - let data = Data(derRepresentation) - var error: Unmanaged? = nil - - // We can't know in DER if this is PKCS8 or PKCS1 without just trying to decode it. - let keyData: Data - if let pkcs8Data = data.pkcs8RSAKeyBytes { - keyData = pkcs8Data - } else { - keyData = data - } - - let key = SecKeyCreateWithData(keyData as CFData, keyAttributes as CFDictionary, &error) - - guard let unwrappedKey = key else { - // If this returns nil, error must be set. - throw error!.takeRetainedValue() as Error - } - - self.backing = unwrappedKey - } - - init(keySize: _RSA.Signing.KeySize) throws { - let keyAttributes: [CFString: Any] = [ - kSecAttrKeyType: kSecAttrKeyTypeRSA, - kSecAttrKeyClass: kSecAttrKeyClassPrivate, - kSecAttrKeySizeInBits: keySize.bitCount - ] - var error: Unmanaged? = nil - let key = SecKeyCreateRandomKey(keyAttributes as CFDictionary, &error) - - guard let unwrappedKey = key else { - // If this returns nil, error must be set. - throw error!.takeRetainedValue() as Error - } - - self.backing = unwrappedKey - } - - init(_ boringSSLKey: BoringSSLRSAPrivateKey) throws { - try self.init(derRepresentation: boringSSLKey.derRepresentation) - } - - var derRepresentation: Data { - var error: Unmanaged? = nil - let representation = SecKeyCopyExternalRepresentation(self.backing, &error) - return representation! as Data - } - - var pemRepresentation: String { - return ASN1.PEMDocument(type: _RSA.PKCS1KeyType, derBytes: self.derRepresentation).pemString - } - - var pkcs8PEMRepresentation: String { - let pkcs1Bytes = self.derRepresentation - let pkcs8Bytes = Data(privateKeyPKCS8BytesForPKCS1Bytes: pkcs1Bytes) - let pemString = ASN1.PEMDocument(type: _RSA.PKCS8KeyType, derBytes: pkcs8Bytes).pemString - - // The BoringSSL implementation returns this string with a trailing newline. For consistency, - // we'll do the same here. - return pemString.appending("\n") - } - - var pkcs8DERRepresentation: Data { - let pkcs1Bytes = self.derRepresentation - let pkcs8Bytes = Data(privateKeyPKCS8BytesForPKCS1Bytes: pkcs1Bytes) - return pkcs8Bytes - } - - var keySizeInBits: Int { - SecKeyGetBlockSize(self.backing) * 8 - } - - var publicKey: SecurityRSAPublicKey { - SecurityRSAPublicKey(SecKeyCopyPublicKey(self.backing)!) - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension SecurityRSAPrivateKey { - internal func signature(for digest: D, padding: _RSA.Signing.Padding) throws -> _RSA.Signing.RSASignature { - let algorithm = try SecKeyAlgorithm(digestType: D.self, padding: padding) - let digestToSign = Data(digest) - var error: Unmanaged? = nil - let sig = SecKeyCreateSignature(self.backing, algorithm, digestToSign as CFData, &error) - - guard let signature = sig else { - // If this returns nil, error must be set. - throw error!.takeRetainedValue() as Error - } - - return _RSA.Signing.RSASignature(rawRepresentation: signature as Data) - } - } - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) - extension SecurityRSAPrivateKey { - internal func decrypt(_ data: D, padding: _RSA.Encryption.Padding) throws -> Data { - let algorithm = try SecKeyAlgorithm(padding: padding) - let dataToDecrypt = Data(data) - var error: Unmanaged? = nil - let dec = SecKeyCreateDecryptedData(self.backing, algorithm, dataToDecrypt as CFData, &error) - - guard let decrypted = dec else { - throw error!.takeRetainedValue() as Error - } - - return decrypted as Data - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension SecurityRSAPublicKey { - func isValidSignature(_ signature: _RSA.Signing.RSASignature, for digest: D, padding: _RSA.Signing.Padding) -> Bool { - do { - let algorithm = try SecKeyAlgorithm(digestType: D.self, padding: padding) - let digestToValidate = Data(digest) - var error: Unmanaged? = nil - let result = SecKeyVerifySignature(self.backing, - algorithm, - digestToValidate as CFData, - signature.rawRepresentation as CFData, - &error) - - return result - } catch { - return false - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension SecurityRSAPublicKey { - internal func encrypt(_ data: D, padding: _RSA.Encryption.Padding) throws -> Data { - let algorithm = try SecKeyAlgorithm(padding: padding) - let dataToEncrypt = Data(data) - var error: Unmanaged? = nil - let enc = SecKeyCreateEncryptedData(self.backing, algorithm, dataToEncrypt as CFData, &error) - - guard let encrypted = enc else { - throw error!.takeRetainedValue() as Error - } - - return encrypted as Data - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension SecKeyAlgorithm { - fileprivate init(digestType: D.Type = D.self, padding: _RSA.Signing.Padding) throws { - switch (digestType, padding.backing) { - case (is Insecure.SHA1.Digest.Type, .pss): - self = .rsaSignatureDigestPSSSHA1 - case (is Insecure.SHA1.Digest.Type, .pkcs1v1_5): - self = .rsaSignatureDigestPKCS1v15SHA1 - case (is SHA256.Digest.Type, .pss): - self = .rsaSignatureDigestPSSSHA256 - case (is SHA256.Digest.Type, .pkcs1v1_5): - self = .rsaSignatureDigestPKCS1v15SHA256 - case (is SHA384.Digest.Type, .pss): - self = .rsaSignatureDigestPSSSHA384 - case (is SHA384.Digest.Type, .pkcs1v1_5): - self = .rsaSignatureDigestPKCS1v15SHA384 - case (is SHA512.Digest.Type, .pss): - self = .rsaSignatureDigestPSSSHA512 - case (is SHA512.Digest.Type, .pkcs1v1_5): - self = .rsaSignatureDigestPKCS1v15SHA512 - case (_, .pssZero): - // Explicitly unsupported: only used in RSABSSA, which is implemented using BoringSSL on all platforms. - throw CryptoKitError.incorrectParameterSize - default: - throw CryptoKitError.incorrectParameterSize - } - } - - fileprivate init(padding: _RSA.Encryption.Padding) throws { - switch padding.backing { - case .pkcs1_oaep(let digest): - switch digest { - case .sha1: - self = .rsaEncryptionOAEPSHA1 - case .sha256: - self = .rsaEncryptionOAEPSHA256 - } - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension Data { - init(_ digest: D) { - self = digest.withUnsafeBytes { Data($0) } - } - - /// A partial PKCS8 DER prefix. This specifically is the version and private key algorithm identifier. - private static let partialPKCS8Prefix = Data( - [ - 0x02, 0x01, 0x00, // Version, INTEGER 0 - 0x30, 0x0d, // SEQUENCE, length 13 - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, // rsaEncryption OID - 0x05, 0x00 // NULL - ] - ) - - var pkcs8RSAKeyBytes: Data? { - // This is PKCS8. A bit awkward now. Rather than bring over the fully-fledged ASN.1 code from - // the main module and all its dependencies, we have a little hand-rolled verifier. To be a proper - // PKCS8 key, this should match: - // - // PrivateKeyInfo ::= SEQUENCE { - // version Version, - // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - // privateKey PrivateKey, - // attributes [0] IMPLICIT Attributes OPTIONAL } - // - // Version ::= INTEGER - // - // PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - // - // PrivateKey ::= OCTET STRING - // - // Attributes ::= SET OF Attribute - // - // We know the version and algorithm identifier, so we can just strip the bytes we'd expect to see here. We do validate - // them though. - precondition(self.startIndex == 0) - - guard self.count >= 4 + Data.partialPKCS8Prefix.count + 4 else { - return nil - } - - // First byte will be the tag for sequence, 0x30. - guard self[0] == 0x30 else { - return nil - } - - // The next few bytes will be a length. We'll expect it to be 3 bytes long, with the first byte telling us - // that it's 3 bytes long. - let lengthLength = Int(self[1]) - guard lengthLength == 0x82 else { - return nil - } - - let length = Int(self[2]) << 8 | Int(self[3]) - guard length == self.count - 4 else { - return nil - } - - // Now we can check the version through the algorithm identifier against the hardcoded values. - guard self.dropFirst(4).prefix(Data.partialPKCS8Prefix.count) == Data.partialPKCS8Prefix else { - return nil - } - - // Ok, the last check are the next 4 bytes, which should now be the tag for OCTET STRING followed by another length. - guard self[4 + Data.partialPKCS8Prefix.count] == 0x04, - self[4 + Data.partialPKCS8Prefix.count + 1] == 0x82 else { - return nil - } - - let octetStringLength = Int(self[4 + Data.partialPKCS8Prefix.count + 2]) << 8 | - Int(self[4 + Data.partialPKCS8Prefix.count + 3]) - guard octetStringLength == self.count - 4 - Data.partialPKCS8Prefix.count - 4 else { - return nil - } - - return self.dropFirst(4 + Data.partialPKCS8Prefix.count + 4) - } - - // Corresponds to the ASN.1 encoding of the RSA AlgorithmIdentifier: - // - // SEQUENCE of OID (:rsaEncryption) and NULL. - static let rsaAlgorithmIdentifierBytes = Data([ - 0x30, 0x0D, // SEQUENCE, Length 13 - 0x06, 0x09, // OID, length 9 - 0x2A, 0x86 , 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, // 1.2.840.113549.1.1.1 :rsaEncryption - 0x05, 0x00, // NULL, length 0 - - ]) - - fileprivate init(spkiBytesForPKCS1Bytes pkcs1Bytes: Data) { - // This does an ad-hoc SPKI encode. Ideally we'd bring over the entire ASN.1 stack, but it's not worth doing - // for just this one use-case. - let keyLength = (pkcs1Bytes.count + 1) - let bitStringOverhead = 1 + keyLength._bytesNeededToEncodeASN1Length // 1 byte for tag. - let totalLengthOfSequencePayload = Self.rsaAlgorithmIdentifierBytes.count + bitStringOverhead + keyLength - - var bytes = Data() - bytes.reserveCapacity(1 + totalLengthOfSequencePayload._bytesNeededToEncodeASN1Length + totalLengthOfSequencePayload) - - bytes.append(0x30) // SEQUENCE marker. - bytes.appendAsASN1NodeLength(totalLengthOfSequencePayload) - bytes.append(Self.rsaAlgorithmIdentifierBytes) - - bytes.append(0x03) // BITSTRING marker - bytes.appendAsASN1NodeLength(keyLength) - bytes.append(UInt8(0)) // No padding bits - bytes.append(contentsOf: pkcs1Bytes) - - self = bytes - } - - static let pkcs8versionIdentifierBytes = Data([ - 0x02, 0x01, 0x00, // Version, INTEGER 0 - ]) - - fileprivate init(privateKeyPKCS8BytesForPKCS1Bytes pkcs1Bytes: Data) { - // The PKCS8 encoding of a private key is very similar to the - // SPKI encoding of a public key, as implemented in `Data(spkiBytesForPKCS1Bytes:)` above. - // The difference is that PKCS 8 includes a VERSION field, and - // uses an OCTET STREAM instead of a BIT STREAM. - let versionLength = Self.pkcs8versionIdentifierBytes.count - let keyLength = (pkcs1Bytes.count) - let octetStringOverhead = keyLength._bytesNeededToEncodeASN1Length + 1 - let totalLengthOfSequencePayload = versionLength + Self.rsaAlgorithmIdentifierBytes.count + octetStringOverhead + keyLength - - var bytes = Data() - bytes.reserveCapacity(1 + totalLengthOfSequencePayload._bytesNeededToEncodeASN1Length + totalLengthOfSequencePayload) - - bytes.append(0x30) // SEQUENCE marker. - bytes.appendAsASN1NodeLength(totalLengthOfSequencePayload) - bytes.append(Self.pkcs8versionIdentifierBytes) - bytes.append(Self.rsaAlgorithmIdentifierBytes) - - bytes.append(0x04) // OCTET STRING marker - bytes.appendAsASN1NodeLength(keyLength) - bytes.append(contentsOf: pkcs1Bytes) - - self = bytes - } - - fileprivate mutating func appendAsASN1NodeLength(_ length: Int) { - let bytesNeeded = length._bytesNeededToEncodeASN1Length - - if bytesNeeded == 1 { - self.append(UInt8(length)) - } else { - // We first write the number of length bytes - // we need, setting the high bit. Then we write the bytes of the length. - self.append(0x80 | UInt8(bytesNeeded - 1)) - - for shift in (0..<(bytesNeeded - 1)).reversed() { - // Shift and mask the integer. - self.append(UInt8(truncatingIfNeeded: (length >> (shift * 8)))) - } - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension Int { - fileprivate var _bytesNeededToEncodeASN1Length: Int { - // ASN.1 lengths are in two forms. If we can store the length in 7 bits, we should: - // that requires only one byte. Otherwise, we need multiple bytes: work out how many, - // plus one for the length of the length bytes. - if self <= 0x7F { - return 1 - } else { - // We need to work out how many bytes we need. There are many fancy bit-twiddling - // ways of doing this, but honestly we don't do this enough to need them, so we'll - // do it the easy way. This math is done on UInt because it makes the shift semantics clean. - // We save a branch here because we can never overflow this addition. - return UInt(self).neededBytes &+ 1 - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension UInt { - // Bytes needed to store a given integer in 7 bit bytes. - fileprivate var neededBytes: Int { - let neededBits = self.bitWidth - self.leadingZeroBitCount - return (neededBits + 7) / 8 - } -} - -#endif From 93a2ebfad71baa299c2ffdc10fb505e05494252f Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Wed, 2 Jul 2025 21:31:02 +0100 Subject: [PATCH 07/36] Add API for ARC(P-256) and deprecate ARC(P-384) (#374) ## Motivation The ARC IETF draft has been updated to now support P256 and drop support for P384. ## Modifications - Update the internal ARC implementation to accommodate multiple curves - Add API surface for P256 - Deprecate API for P384 - Add tests for P256 with test vectors from the draft - Move over the end-to-end API tests to P256 - Add benchmarks for P256 ## Result - New API `P256._ARCV1`, which provides an implementation of ARC(P-256). - Deprecate `P384._ARCV1`, which provides an implementation of ARC(P-256). [^1]: https://chris-wood.github.io/draft-arc/draft-yun-cfrg-arc.html#name-arcv1-p256 --------- Co-authored-by: Cory Benfield --- Benchmarks/Benchmarks/Benchmarks.swift | 59 +++ Sources/_CryptoExtras/ARC/ARC+API.swift | 402 +++++++++++++++++- Sources/_CryptoExtras/ARC/ARC.swift | 17 +- Sources/_CryptoExtras/ARC/ARCCredential.swift | 2 +- Sources/_CryptoExtras/ARC/ARCEncoding.swift | 205 ++++----- .../_CryptoExtras/ARC/ARCPrecredential.swift | 4 +- .../_CryptoExtras/ARC/ARCPresentation.swift | 16 +- Sources/_CryptoExtras/ARC/ARCRequest.swift | 8 +- Sources/_CryptoExtras/ARC/ARCResponse.swift | 10 +- Sources/_CryptoExtras/ARC/ARCServer.swift | 10 +- .../_CryptoExtrasTests/ARC/ARCAPITests.swift | 216 +++++++++- .../ARC/ARCEncodingTests.swift | 75 ++-- .../ARC/ARCPublicAPITests.swift | 12 +- .../ARC/ARCTestVectors.swift | 81 +++- Tests/_CryptoExtrasTests/ARC/ARCTests.swift | 8 +- 15 files changed, 924 insertions(+), 201 deletions(-) diff --git a/Benchmarks/Benchmarks/Benchmarks.swift b/Benchmarks/Benchmarks/Benchmarks.swift index 64626f573..b7e2d241d 100644 --- a/Benchmarks/Benchmarks/Benchmarks.swift +++ b/Benchmarks/Benchmarks/Benchmarks.swift @@ -19,6 +19,65 @@ import _CryptoExtras let benchmarks = { let defaultMetrics: [BenchmarkMetric] = [.mallocCountTotal, .cpuTotal] + Benchmark( + "arc-issue-p256", + configuration: Benchmark.Configuration( + metrics: defaultMetrics, + scalingFactor: .kilo, + maxDuration: .seconds(10_000_000), + maxIterations: 3 + ) + ) { benchmark in + let privateKey = P256._ARCV1.PrivateKey() + let publicKey = privateKey.publicKey + let requestContext = Data("shared request context".utf8) + let precredential = try publicKey.prepareCredentialRequest(requestContext: requestContext) + let credentialRequest = precredential.credentialRequest + + benchmark.startMeasurement() + + for _ in benchmark.scaledIterations { + blackHole(try privateKey.issue(credentialRequest)) + } + } + + Benchmark( + "arc-verify-p256", + configuration: Benchmark.Configuration( + metrics: defaultMetrics, + scalingFactor: .kilo, + maxDuration: .seconds(10_000_000), + maxIterations: 10 + ) + ) { benchmark in + let privateKey = P256._ARCV1.PrivateKey() + let publicKey = privateKey.publicKey + let requestContext = Data("shared request context".utf8) + let (presentationContext, presentationLimit) = (Data("shared presentation context".utf8), 2) + let precredential = try publicKey.prepareCredentialRequest(requestContext: requestContext) + let credentialRequest = precredential.credentialRequest + let credentialResponse = try privateKey.issue(credentialRequest) + var credential = try publicKey.finalize(credentialResponse, for: precredential) + let (presentation, nonce) = try credential.makePresentation( + context: presentationContext, + presentationLimit: presentationLimit + ) + + benchmark.startMeasurement() + + for _ in benchmark.scaledIterations { + blackHole( + try privateKey.verify( + presentation, + requestContext: requestContext, + presentationContext: presentationContext, + presentationLimit: presentationLimit, + nonce: nonce + ) + ) + } + } + Benchmark( "arc-issue-p384", configuration: Benchmark.Configuration( diff --git a/Sources/_CryptoExtras/ARC/ARC+API.swift b/Sources/_CryptoExtras/ARC/ARC+API.swift index 3a29f85bb..2df96a7b6 100644 --- a/Sources/_CryptoExtras/ARC/ARC+API.swift +++ b/Sources/_CryptoExtras/ARC/ARC+API.swift @@ -14,8 +14,388 @@ import Crypto import Foundation +// MARK: - P256 + ARC(P-256) +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256 { + /// Anonymous Rate-Limited Credentials (ARC). + /// + /// A specialization of keyed-verification anonymous credentials with support for rate limiting. + /// + /// - Seealso: [IETF Internet Draft: draft-yun-cfrg-arc-00](https://datatracker.ietf.org/doc/draft-yun-cfrg-arc). + public enum _ARCV1 { + internal typealias H2G = HashToCurveImpl + internal typealias Ciphersuite = ARC.Ciphersuite + fileprivate typealias Server = ARC.Server + + internal static let ciphersuite = Ciphersuite(H2G.self) + } +} + +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1 { + /// The server secrets used to issue and verify credentials. + public struct PrivateKey: Sendable { + fileprivate var backing: ARC.Server + + /// Creates a random private key for ARC(P-256). + public init() { + self.backing = ARC.Server(ciphersuite: P256._ARCV1.ciphersuite) + } + + // The spec does not define a serialization of the private key since, unlike the public key, it is not an + // interop concern. + // + // This initializer expects a concatenation of the binary representations of the private scalars: + // + // struct { + // uint8 x0[Ne]; + // uint8 x1[Ne]; + // uint8 x2[Ne]; + // uint8 x0Blinding[Ne]; + // } ServerPrivateKey; + // + public init(rawRepresentation: D) throws { + guard rawRepresentation.count == 4 * P256.orderByteCount else { + throw ARC.Errors.incorrectPrivateKeyDataSize + } + + var bytes = Data(rawRepresentation)[...] + let x0 = try H2G.G.Scalar(bytes: bytes[.. + + fileprivate init(backing: ARC.ServerPublicKey) { + self.backing = backing + } + + fileprivate static var serializedByteCount: Int { 3 * P256.compressedx962PointByteCount } + + // The spec defines this serialization of the public key: + // + // struct { + // uint8 X0[Ne]; + // uint8 X1[Ne]; + // uint8 X2[Ne]; + // } ServerPublicKey; + // + public init(rawRepresentation: D) throws { + guard rawRepresentation.count == Self.serializedByteCount else { throw ARC.Errors.incorrectPublicKeyDataSize } + + var bytes = Data(rawRepresentation)[...] + let X0 = try H2G.G.Element(oprfRepresentation: bytes[.. + + fileprivate init(backing: ARC.CredentialRequest) { + self.backing = backing + } + + public init(rawRepresentation: D) throws { + self.backing = try ARC.CredentialRequest.deserialize(requestData: rawRepresentation, ciphersuite: P256._ARCV1.ciphersuite) + } + + public var rawRepresentation: Data { + self.backing.serialize(ciphersuite: P256._ARCV1.ciphersuite) + } + } + + /// A credential request to be sent to the server, and associated client secrets. + /// + /// Users cannot create values of this type manually; they are created using the prepare method on the public key. + public struct Precredential: Sendable { + /// This backing type binds many things together, including the server commitments, client secrets, credential + /// request, and presentation limit. + internal var backing: ARC.Precredential + + /// The credential request to be sent to the server. + public var credentialRequest: CredentialRequest { + CredentialRequest(backing: self.backing.credentialRequest) + } + } + + /// A credential response, created by the server, to be sent to the client. + /// + /// Servers should not create values of this type manually; they should use the issue method on the private key. + /// + /// Clients should reconstruct values of this type from the serialized bytes sent by the server. + public struct CredentialResponse: Sendable { + var backing: ARC.CredentialResponse + + fileprivate init(backing: ARC.CredentialResponse) { + self.backing = backing + } + + public init(rawRepresentation: D) throws { + self.backing = try ARC.CredentialResponse.deserialize(responseData: rawRepresentation, ciphersuite: P256._ARCV1.ciphersuite) + } + + public var rawRepresentation: Data { + self.backing.serialize(ciphersuite: P256._ARCV1.ciphersuite) + } + } + + + /// A credential, created by the client using the response from the server. + /// + /// Users cannot create values of this type manually; they are created using the issue method on the public key. + public struct Credential: Sendable { + var backing: ARC.Credential + + fileprivate init(backing: ARC.Credential) { + self.backing = backing + } + } + + /// A presentation, created by the client from a credential, to be sent to the server to verify. + /// + /// Users cannot create values of this type manually; they are created using the present method on the credential. + public struct Presentation: Sendable { + internal var backing: ARC.Presentation + + fileprivate init(backing: ARC.Presentation) { + self.backing = backing + } + + public init(rawRepresentation: D) throws { + self.backing = try ARC.Presentation.deserialize(presentationData: rawRepresentation, ciphersuite: P256._ARCV1.ciphersuite) + } + + public var rawRepresentation: Data { + self.backing.serialize(ciphersuite: P256._ARCV1.ciphersuite) + } + + public var tag: Data { + self.backing.tag.compressedRepresentation + } + } +} + +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.PublicKey { + internal func prepareCredentialRequest( + requestContext: D, + m1: P256._ARCV1.H2G.G.Scalar, + r1: P256._ARCV1.H2G.G.Scalar, + r2: P256._ARCV1.H2G.G.Scalar + ) throws -> P256._ARCV1.Precredential { + let precedential = try ARC.Precredential( + ciphersuite: P256._ARCV1.ciphersuite, + m1: m1, + requestContext: Data(requestContext), + r1: r1, + r2: r2, + serverPublicKey: self.backing + ) + return P256._ARCV1.Precredential(backing: precedential) + } + + /// Prepare a credential request for a given request context. + /// + /// - Parameters: + /// - requestContext: Request context, agreed with the server. + /// + /// - Returns: A precredential containing the client secrets, and request to be sent to the server. + public func prepareCredentialRequest( + requestContext: D + ) throws -> P256._ARCV1.Precredential { + try self.prepareCredentialRequest( + requestContext: requestContext, + m1: .random, + r1: .random, + r2: .random + ) + } +} + +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.PrivateKey { + internal func issue( + _ credentialRequest: P256._ARCV1.CredentialRequest, + b: P256._ARCV1.H2G.G.Scalar + ) throws -> P256._ARCV1.CredentialResponse { + let response = try self.backing.respond(credentialRequest: credentialRequest.backing, b: b) + return P256._ARCV1.CredentialResponse(backing: response) + } + + /// Generate a credential response from a credential request. + public func issue(_ credentialRequest: P256._ARCV1.CredentialRequest) throws -> P256._ARCV1.CredentialResponse { + try self.issue(credentialRequest, b: .random) + } +} + +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.PublicKey { + /// Create a credential from the issuer response. + public func finalize( + _ credentialResponse: P256._ARCV1.CredentialResponse, + for precredential: P256._ARCV1.Precredential + ) throws -> P256._ARCV1.Credential { + let credential = try precredential.backing.makeCredential(credentialResponse: credentialResponse.backing) + return P256._ARCV1.Credential(backing: credential) + } +} + +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.Credential { + internal mutating func makePresentation( + context: D, + presentationLimit: Int, + fixedNonce: Int?, + a: P256._ARCV1.H2G.G.Scalar, + r: P256._ARCV1.H2G.G.Scalar, + z: P256._ARCV1.H2G.G.Scalar + ) throws -> (presentation: P256._ARCV1.Presentation, nonce: Int) { + let (presentation, nonce) = try self.backing.makePresentation( + presentationContext: Data(context), + presentationLimit: presentationLimit, + a: a, + r: r, + z: z, + optionalNonce: fixedNonce + ) + return (P256._ARCV1.Presentation(backing: presentation), nonce) + } + + /// Create a presentation to provide to a verifier. + /// + /// - Parameters: + /// - context: The presentation context agreed with the verifier. + /// - presentationLimit: The presentation limit to enforce. + /// + /// - Returns: A presentation of this credential. + /// + /// - Throws: An error if the presentation limit for this credential has been exceeded. + public mutating func makePresentation( + context: D, + presentationLimit: Int + ) throws -> (presentation: P256._ARCV1.Presentation, nonce: Int) { + try self.makePresentation( + context: context, + presentationLimit: presentationLimit, + fixedNonce: nil, + a: .random, + r: .random, + z: .random + ) + } +} + +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.PrivateKey { + /// Verify a presentation is valid for a given attribute. + /// + /// Presentation verification includes checking that: + /// 1. The presentation is for the expected request context. + /// 2. The presentation is for the expected presentation context. + /// 3. The presentation nonce is appropriate for the presentation limit. + /// 4. The presentation proof is valid. + /// + /// - Parameters: + /// - presentation: The presentation to verify. + /// - requestContext: The expected request context encoded within the presentation. + /// - presentationContext: The expected presentation context encoded within the presentation. + /// - presentationLimit: The presentation limit to enforce. + /// - nonce: The expected nonce encoded within the presentation. + /// + /// - Returns: True if the presentation is valid, false otherwise. + public func verify( + _ presentation: P256._ARCV1.Presentation, + requestContext: D1, + presentationContext: D2, + presentationLimit: Int, + nonce: Int + ) throws -> Bool { + try self.backing.verify( + presentation: presentation.backing, + requestContext: Data(requestContext), + presentationContext: Data(presentationContext), + presentationLimit: presentationLimit, + nonce: nonce + ) + } +} + // MARK: - P384 + ARC(P-384) @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") extension P384 { /// Anonymous Rate-Limited Credentials (ARC). /// @@ -24,14 +404,15 @@ extension P384 { /// - Seealso: [IETF Internet Draft: draft-yun-cfrg-arc-00](https://datatracker.ietf.org/doc/draft-yun-cfrg-arc). public enum _ARCV1 { internal typealias H2G = HashToCurveImpl - fileprivate typealias Ciphersuite = ARC.Ciphersuite + internal typealias Ciphersuite = ARC.Ciphersuite fileprivate typealias Server = ARC.Server - fileprivate static var ciphersuite: Ciphersuite { Ciphersuite(H2G.self) } + internal static let ciphersuite = Ciphersuite(H2G.self) } } @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") extension P384._ARCV1 { /// The server secrets used to issue and verify credentials. public struct PrivateKey: Sendable { @@ -169,11 +550,11 @@ extension P384._ARCV1 { } public init(rawRepresentation: D) throws { - self.backing = try ARC.CredentialRequest.deserialize(requestData: rawRepresentation) + self.backing = try ARC.CredentialRequest.deserialize(requestData: rawRepresentation, ciphersuite: P384._ARCV1.ciphersuite) } public var rawRepresentation: Data { - self.backing.serialize() + self.backing.serialize(ciphersuite: P384._ARCV1.ciphersuite) } } @@ -204,11 +585,11 @@ extension P384._ARCV1 { } public init(rawRepresentation: D) throws { - self.backing = try ARC.CredentialResponse.deserialize(responseData: rawRepresentation) + self.backing = try ARC.CredentialResponse.deserialize(responseData: rawRepresentation, ciphersuite: P384._ARCV1.ciphersuite) } public var rawRepresentation: Data { - self.backing.serialize() + self.backing.serialize(ciphersuite: P384._ARCV1.ciphersuite) } } @@ -235,11 +616,11 @@ extension P384._ARCV1 { } public init(rawRepresentation: D) throws { - self.backing = try ARC.Presentation.deserialize(presentationData: rawRepresentation) + self.backing = try ARC.Presentation.deserialize(presentationData: rawRepresentation, ciphersuite: P384._ARCV1.ciphersuite) } public var rawRepresentation: Data { - self.backing.serialize() + self.backing.serialize(ciphersuite: P384._ARCV1.ciphersuite) } public var tag: Data { @@ -249,6 +630,7 @@ extension P384._ARCV1 { } @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") extension P384._ARCV1.PublicKey { internal func prepareCredentialRequest( requestContext: D, @@ -286,6 +668,7 @@ extension P384._ARCV1.PublicKey { } @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") extension P384._ARCV1.PrivateKey { internal func issue( _ credentialRequest: P384._ARCV1.CredentialRequest, @@ -302,6 +685,7 @@ extension P384._ARCV1.PrivateKey { } @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") extension P384._ARCV1.PublicKey { /// Create a credential from the issuer response. public func finalize( @@ -314,6 +698,7 @@ extension P384._ARCV1.PublicKey { } @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") extension P384._ARCV1.Credential { internal mutating func makePresentation( context: D, @@ -359,6 +744,7 @@ extension P384._ARCV1.Credential { } @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") extension P384._ARCV1.PrivateKey { /// Verify a presentation is valid for a given attribute. /// diff --git a/Sources/_CryptoExtras/ARC/ARC.swift b/Sources/_CryptoExtras/ARC/ARC.swift index 73bda212a..0cc645880 100644 --- a/Sources/_CryptoExtras/ARC/ARC.swift +++ b/Sources/_CryptoExtras/ARC/ARC.swift @@ -21,8 +21,6 @@ enum ARC {} @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) extension ARC { - static let domain = "ARCV1-P384" - enum Errors: Error { case invalidProof case invalidPresentationLimit @@ -40,26 +38,33 @@ extension ARC { /// Ciphersuites for Anonymous Rate-Limited Credentials (ARC) struct Ciphersuite { let suiteID: Int + let domain: String + let scalarByteCount: Int + let pointByteCount: Int init(_ h2g: H2G.Type) { switch h2g.self { case is HashToCurveImpl.Type: self.suiteID = 3 + self.domain = "ARCV1-P256" + self.scalarByteCount = P256.orderByteCount + self.pointByteCount = P256.compressedx962PointByteCount case is HashToCurveImpl.Type: self.suiteID = 4 - case is HashToCurveImpl.Type: - self.suiteID = 5 + self.domain = "ARCV1-P384" + self.scalarByteCount = P384.orderByteCount + self.pointByteCount = P384.compressedx962PointByteCount default: fatalError("Anonymous Rate-Limited Credentials (ARC) only support corecrypto H2G.") } } } - static func getGenerators(suite _: Ciphersuite) -> ( + static func getGenerators(suite: Ciphersuite) -> ( generatorG: H2G.G.Element, generatorH: H2G.G.Element ) { let generatorG = H2G.G.Element.generator - let generatorH = H2G.hashToGroup(generatorG.oprfRepresentation, domainSeparationString: Data(("HashToGroup-" + ARC.domain + "generatorH").utf8)) + let generatorH = H2G.hashToGroup(generatorG.oprfRepresentation, domainSeparationString: Data(("HashToGroup-" + suite.domain + "generatorH").utf8)) return (generatorG, generatorH) } } diff --git a/Sources/_CryptoExtras/ARC/ARCCredential.swift b/Sources/_CryptoExtras/ARC/ARCCredential.swift index 05442263b..de257e3e1 100644 --- a/Sources/_CryptoExtras/ARC/ARCCredential.swift +++ b/Sources/_CryptoExtras/ARC/ARCCredential.swift @@ -30,7 +30,7 @@ extension ARC { init(credentialResponse: CredentialResponse, credentialRequest: CredentialRequest, clientSecrets: ClientSecrets, serverPublicKey: ServerPublicKey, ciphersuite: Ciphersuite, generatorG: Group.Element, generatorH: Group.Element) throws { // Verify credential response proof guard - try credentialResponse.verify(request: credentialRequest, serverPublicKey: serverPublicKey, generatorG: generatorG, generatorH: generatorH) + try credentialResponse.verify(request: credentialRequest, serverPublicKey: serverPublicKey, generatorG: generatorG, generatorH: generatorH, ciphersuite: ciphersuite) else { throw ARC.Errors.invalidProof } diff --git a/Sources/_CryptoExtras/ARC/ARCEncoding.swift b/Sources/_CryptoExtras/ARC/ARCEncoding.swift index 7c77ab18f..c3c67ae24 100644 --- a/Sources/_CryptoExtras/ARC/ARCEncoding.swift +++ b/Sources/_CryptoExtras/ARC/ARCEncoding.swift @@ -14,148 +14,155 @@ import Foundation import Crypto -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -typealias ARCCurve = P384 @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -typealias ARCH2G = HashToCurveImpl +typealias ARCP256 = HashToCurveImpl +@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) +typealias ARCP384 = HashToCurveImpl @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -extension ARC.CredentialRequest where H2G == ARCH2G { - static let scalarCount = 5 - static let serializedByteCount = 2 * ARCCurve.compressedx962PointByteCount + Self.scalarCount * ARCCurve.orderByteCount - - func serialize() -> Data { - var result = Data(capacity: Self.serializedByteCount) - result.append(self.m1Enc.compressedRepresentation) - result.append(self.m2Enc.compressedRepresentation) - result.append(self.proof.serialize()) +extension ARC.CredentialRequest { + static func getScalarCount() -> Int { return 5 } + static func getSerializedByteCount(_ ciphersuite: ARC.Ciphersuite) -> Int { + return 2 * ciphersuite.pointByteCount + Self.getScalarCount() * ciphersuite.scalarByteCount + } + + func serialize(ciphersuite: ARC.Ciphersuite) -> Data { + var result = Data(capacity: Self.getSerializedByteCount(ciphersuite)) + result.append(self.m1Enc.oprfRepresentation) + result.append(self.m2Enc.oprfRepresentation) + result.append(self.proof.serialize(ciphersuite: ciphersuite)) return result } - static func deserialize(requestData: D) throws -> ARC.CredentialRequest { - guard requestData.count == Self.serializedByteCount else { + static func deserialize(requestData: D, ciphersuite: ARC.Ciphersuite) throws -> ARC.CredentialRequest { + guard requestData.count == Self.getSerializedByteCount(ciphersuite) else { throw ARC.Errors.incorrectRequestDataSize } var bytes = Data(requestData) - let m1Enc = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let m2Enc = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let proof = try Proof.deserialize(proofData: bytes, scalarCount: Self.scalarCount) + let m1Enc = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let m2Enc = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let proof = try Proof.deserialize(proofData: bytes, scalarCount: Self.getScalarCount(), ciphersuite: ciphersuite) return ARC.CredentialRequest(m1Enc: m1Enc, m2Enc: m2Enc, proof: proof) } } @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -extension ARC.CredentialResponse where H2G == ARCH2G { - static let scalarCount = 8 - static let serializedByteCount = 6 * ARCCurve.compressedx962PointByteCount + Self.scalarCount * ARCCurve.orderByteCount +extension ARC.CredentialResponse { + static func getScalarCount() -> Int { return 8 } + static func getSerializedByteCount(_ ciphersuite: ARC.Ciphersuite) -> Int { + return 6 * ciphersuite.pointByteCount + Self.getScalarCount() * ciphersuite.scalarByteCount + } - func serialize() -> Data { - var result = Data(capacity: Self.serializedByteCount) + func serialize(ciphersuite: ARC.Ciphersuite) -> Data { + var result = Data(capacity: Self.getSerializedByteCount(ciphersuite)) - result.append(self.U.compressedRepresentation) - result.append(self.encUPrime.compressedRepresentation) - result.append(self.X0Aux.compressedRepresentation) - result.append(self.X1Aux.compressedRepresentation) - result.append(self.X2Aux.compressedRepresentation) - result.append(self.HAux.compressedRepresentation) - result.append(self.proof.serialize()) + result.append(self.U.oprfRepresentation) + result.append(self.encUPrime.oprfRepresentation) + result.append(self.X0Aux.oprfRepresentation) + result.append(self.X1Aux.oprfRepresentation) + result.append(self.X2Aux.oprfRepresentation) + result.append(self.HAux.oprfRepresentation) + result.append(self.proof.serialize(ciphersuite: ciphersuite)) return result } - static func deserialize(responseData: D) throws -> ARC.CredentialResponse { - guard responseData.count == self.serializedByteCount else { + static func deserialize(responseData: D, ciphersuite: ARC.Ciphersuite) throws -> ARC.CredentialResponse { + guard responseData.count == self.getSerializedByteCount(ciphersuite) else { throw ARC.Errors.incorrectResponseDataSize } var bytes = Data(responseData) - let U = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let encUPrime = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let X0Aux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let X1Aux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let X2Aux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let HAux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) + let U = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let encUPrime = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let X0Aux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let X1Aux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let X2Aux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let HAux = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) - let proof = try Proof.deserialize(proofData: bytes, scalarCount: self.scalarCount) + let proof = try Proof.deserialize(proofData: bytes, scalarCount: Self.getScalarCount(), ciphersuite: ciphersuite) return ARC.CredentialResponse(U: U, encUPrime: encUPrime, X0Aux: X0Aux, X1Aux: X1Aux, X2Aux: X2Aux, HAux: HAux, proof: proof) } } @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -extension ARC.Presentation where H2G == ARCH2G { - static let scalarCount = 5 - static let pointCount = 4 - static let serializedByteCount = pointCount * ARCCurve.compressedx962PointByteCount + scalarCount * ARCCurve.orderByteCount +extension ARC.Presentation { + static func getScalarCount() -> Int { return 5 } + static func getPointCount() -> Int { return 4 } + static func getSerializedByteCount(_ ciphersuite: ARC.Ciphersuite) -> Int { + return Self.getPointCount() * ciphersuite.pointByteCount + Self.getScalarCount() * ciphersuite.scalarByteCount + } - func serialize() -> Data { - var result = Data(capacity: Self.serializedByteCount) + func serialize(ciphersuite: ARC.Ciphersuite) -> Data { + var result = Data(capacity: Self.getSerializedByteCount(ciphersuite)) - result.append(self.U.compressedRepresentation) - result.append(self.UPrimeCommit.compressedRepresentation) - result.append(self.m1Commit.compressedRepresentation) - result.append(self.tag.compressedRepresentation) - result.append(self.proof.serialize()) + result.append(self.U.oprfRepresentation) + result.append(self.UPrimeCommit.oprfRepresentation) + result.append(self.m1Commit.oprfRepresentation) + result.append(self.tag.oprfRepresentation) + result.append(self.proof.serialize(ciphersuite: ciphersuite)) return result } - static func deserialize(presentationData: D) throws -> ARC.Presentation { - guard presentationData.count == self.serializedByteCount else { + static func deserialize(presentationData: D, ciphersuite: ARC.Ciphersuite) throws -> ARC.Presentation { + guard presentationData.count == self.getSerializedByteCount(ciphersuite) else { throw ARC.Errors.incorrectPresentationDataSize } var bytes = Data(presentationData) - let U = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let UPrimeCommit = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let m1Commit = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let tag = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let presentationProof = try Proof.deserialize(proofData: bytes, scalarCount: Self.scalarCount) + let U = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let UPrimeCommit = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let m1Commit = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let tag = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let presentationProof = try Proof.deserialize(proofData: bytes, scalarCount: Self.getScalarCount(), ciphersuite: ciphersuite) return ARC.Presentation(U: U, UPrimeCommit: UPrimeCommit, m1Commit: m1Commit, tag: tag, proof: presentationProof) } } @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -extension ARC.ServerPublicKey where H2G == ARCH2G { - static let serializedByteCount = 3 * ARCCurve.compressedx962PointByteCount - static let pointCount = 3 // TODO: delete +extension ARC.ServerPublicKey { + static func getSerializedByteCount(_ ciphersuite: ARC.Ciphersuite) -> Int { + return 3 * ciphersuite.pointByteCount + } - func serialize() -> Data { - var result = Data(capacity: Self.serializedByteCount) + func serialize(ciphersuite: ARC.Ciphersuite) -> Data { + var result = Data(capacity: Self.getSerializedByteCount(ciphersuite)) - result.append(self.X0.compressedRepresentation) - result.append(self.X1.compressedRepresentation) - result.append(self.X2.compressedRepresentation) + result.append(self.X0.oprfRepresentation) + result.append(self.X1.oprfRepresentation) + result.append(self.X2.oprfRepresentation) return result } - static func deserialize(serverPublicKeyData: D) throws -> ARC.ServerPublicKey { - guard serverPublicKeyData.count == self.pointCount * ARCCurve.compressedx962PointByteCount else { + static func deserialize(serverPublicKeyData: D, ciphersuite: ARC.Ciphersuite) throws -> ARC.ServerPublicKey { + guard serverPublicKeyData.count == self.getSerializedByteCount(ciphersuite) else { throw ARC.Errors.incorrectServerCommitmentsSize } var bytes = Data(serverPublicKeyData) - let X0 = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let X1 = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let X2 = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) + let X0 = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let X1 = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let X2 = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) return ARC.ServerPublicKey(X0: X0, X1: X1, X2: X2) } } @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -extension Proof where H2G == ARCH2G { - func serialize() -> Data { +extension Proof { + func serialize(ciphersuite: ARC.Ciphersuite) -> Data { let scalarCount = self.responses.count + 1 - var result = Data(capacity: scalarCount * ARCCurve.orderByteCount) + var result = Data(capacity: scalarCount * ciphersuite.scalarByteCount) // Serialize challenge result.append(self.challenge.rawRepresentation) @@ -166,21 +173,21 @@ extension Proof where H2G == ARCH2G { return result } - static func deserialize(proofData: D, scalarCount: Int) throws -> Proof { - guard proofData.count == scalarCount * ARCCurve.orderByteCount else { + static func deserialize(proofData: D, scalarCount: Int, ciphersuite: ARC.Ciphersuite) throws -> Proof { + guard proofData.count == scalarCount * ciphersuite.scalarByteCount else { throw ARC.Errors.incorrectProofDataSize } var bytes = Data(proofData) // Deserialize challenge - let challenge = try ARCH2G.G.Scalar(bytes: bytes.popFirst(ARCCurve.orderByteCount)) + let challenge = try H2G.G.Scalar(bytes: bytes.popFirst(ciphersuite.scalarByteCount), reductionIsModOrder: true) // Deserialize responses - var responses: [GroupImpl.Scalar] = [] + var responses: [H2G.G.Scalar] = [] responses.reserveCapacity(scalarCount - 1) for _ in (0.. Int { return 1 } + static func getPointCount() -> Int { return 5 } + static func getSerializedByteCountExcludingPresentationState(_ ciphersuite: ARC.Ciphersuite) -> Int { + return Self.getPointCount() * ciphersuite.pointByteCount + Self.getScalarCount() * ciphersuite.scalarByteCount + } - func serialize() throws -> Data { + func serialize(ciphersuite: ARC.Ciphersuite) throws -> Data { let presentationStateBytes = try self.presentationState.serialize() - - var result = Data(capacity: Self.serializedByteCountExcludingPresentationState + presentationStateBytes.count) + var result = Data(capacity: Self.getSerializedByteCountExcludingPresentationState(ciphersuite) + presentationStateBytes.count) result.append(self.m1.rawRepresentation) - result.append(self.U.compressedRepresentation) - result.append(self.UPrime.compressedRepresentation) - result.append(self.X1.compressedRepresentation) - result.append(self.generatorG.compressedRepresentation) - result.append(self.generatorH.compressedRepresentation) + result.append(self.U.oprfRepresentation) + result.append(self.UPrime.oprfRepresentation) + result.append(self.X1.oprfRepresentation) + result.append(self.generatorG.oprfRepresentation) + result.append(self.generatorH.oprfRepresentation) result.append(presentationStateBytes) return result } - static func deserialize(credentialData: D) throws -> ARC.Credential { - guard credentialData.count - Self.serializedByteCountExcludingPresentationState >= 0 else { + static func deserialize(credentialData: D, ciphersuite: ARC.Ciphersuite) throws -> ARC.Credential { + guard credentialData.count - Self.getSerializedByteCountExcludingPresentationState(ciphersuite) >= 0 else { throw ARC.Errors.incorrectCredentialDataSize } let credentialData = Data(credentialData) var bytes = Data(credentialData) - let m1 = try ARCH2G.G.Scalar(bytes: bytes.popFirst(ARCCurve.orderByteCount)) - let U = try ARCH2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let UPrime = try ARCH2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let X1 = try ARCH2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let genG = try ARCH2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) - let genH = try ARCH2G.G.Element(oprfRepresentation: bytes.popFirst(ARCCurve.compressedx962PointByteCount)) + let m1 = try H2G.G.Scalar(bytes: bytes.popFirst(ciphersuite.scalarByteCount), reductionIsModOrder: true) + let U = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let UPrime = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let X1 = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let genG = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) + let genH = try H2G.G.Element(oprfRepresentation: bytes.popFirst(ciphersuite.pointByteCount)) // Deserialize presentationState from remaining bytes. let presentationState = try ARC.PresentationState.deserialize(presentationStateData: bytes) - let ciphersuite = ARC.Ciphersuite(ARCH2G.self) + let ciphersuite = ARC.Ciphersuite(H2G.self) return ARC.Credential(m1: m1, U: U, UPrime: UPrime, X1: X1, ciphersuite: ciphersuite, generatorG: genG, generatorH: genH, presentationState: presentationState) } } diff --git a/Sources/_CryptoExtras/ARC/ARCPrecredential.swift b/Sources/_CryptoExtras/ARC/ARCPrecredential.swift index 4b3f0cd04..ee21714ab 100644 --- a/Sources/_CryptoExtras/ARC/ARCPrecredential.swift +++ b/Sources/_CryptoExtras/ARC/ARCPrecredential.swift @@ -40,12 +40,12 @@ extension ARC { let credentialRequest: CredentialRequest init(ciphersuite: Ciphersuite, m1: Group.Scalar = Group.Scalar.random, requestContext: Data, r1: Group.Scalar = Group.Scalar.random, r2: Group.Scalar = Group.Scalar.random, serverPublicKey: ServerPublicKey) throws { - let m2 = try H2G.hashToScalar(requestContext, domainSeparationString: Data((ARC.domain + "requestContext").utf8)) + let m2 = try H2G.hashToScalar(requestContext, domainSeparationString: Data((ciphersuite.domain + "requestContext").utf8)) self.clientSecrets = ClientSecrets(m1: m1, m2: m2, r1: r1, r2: r2) self.serverPublicKey = serverPublicKey self.ciphersuite = ciphersuite (self.generatorG, self.generatorH) = ARC.getGenerators(suite: ciphersuite) - self.credentialRequest = try CredentialRequest(clientSecrets: self.clientSecrets, generatorG: generatorG, generatorH: generatorH) + self.credentialRequest = try CredentialRequest(clientSecrets: self.clientSecrets, generatorG: generatorG, generatorH: generatorH, ciphersuite: ciphersuite) } func makeCredential(credentialResponse: CredentialResponse) throws -> Credential { diff --git a/Sources/_CryptoExtras/ARC/ARCPresentation.swift b/Sources/_CryptoExtras/ARC/ARCPresentation.swift index 4cdc69068..e5b86abe4 100644 --- a/Sources/_CryptoExtras/ARC/ARCPresentation.swift +++ b/Sources/_CryptoExtras/ARC/ARCPresentation.swift @@ -45,9 +45,9 @@ extension ARC { let V = z * credential.X1 - r * generatorG // Create tag: (m1 + nonce)^(-1) * H2G(presentationContext) - let nonceScalar = try Group.Scalar(bytes: I2OSP(value: nonce, outputByteCount: ARCCurve.orderByteCount), reductionIsModOrder: true) + let nonceScalar = try Group.Scalar(bytes: I2OSP(value: nonce, outputByteCount: credential.ciphersuite.scalarByteCount), reductionIsModOrder: true) let inverse = (nonceScalar + credential.m1) ^ (-1) - let T = H2G.hashToGroup(presentationContext, domainSeparationString: Data(("HashToGroup-" + ARC.domain + "Tag").utf8)) + let T = H2G.hashToGroup(presentationContext, domainSeparationString: Data(("HashToGroup-" + credential.ciphersuite.domain + "Tag").utf8)) let tag = inverse * T // m1Tag is a helper element in the ZKP, and is needed to ensure the @@ -55,7 +55,7 @@ extension ARC { let m1Tag = credential.m1 * tag // Create a prover, and allocate variables for the constrained scalars. - var prover = Prover(label: ARC.domain + ARC.domain + "CredentialPresentation") + var prover = Prover(label: credential.ciphersuite.domain + credential.ciphersuite.domain + "CredentialPresentation") let m1Var = prover.appendScalar(label: "m1", assignment: credential.m1) let zVar = prover.appendScalar(label: "z", assignment: z) let rNegVar = prover.appendScalar(label: "-r", assignment: -r) @@ -86,12 +86,10 @@ extension ARC { - nonce: Integer which is used for rate limiting, which should be in `[0, presentationLimit)`. - generatorG: Public generator G - generatorH: Public generator H + - ciphersuite: The ciphersuite for ARC - Returns: a boolean for if the tag is valid and the tag proof verifies correctly. */ - func verify( - serverPrivateKey: ServerPrivateKey, X1: Group.Element, m2: Group.Scalar, presentationContext: Data, presentationLimit: Int, nonce: Int, - generatorG: Group.Element, generatorH: Group.Element - ) throws -> Bool { + func verify(serverPrivateKey: ServerPrivateKey, X1: Group.Element, m2: Group.Scalar, presentationContext: Data, presentationLimit: Int, nonce: Int, generatorG: Group.Element, generatorH: Group.Element, ciphersuite: Ciphersuite) throws -> Bool { if nonce < 0 || nonce >= presentationLimit { return false // nonce is outside of the presentationLimit } @@ -103,14 +101,14 @@ extension ARC { let V = serverPrivateKey.x0 * self.U + serverPrivateKey.x1 * self.m1Commit + serverPrivateKey.x2 * m2 * self.U - self.UPrimeCommit // Recompute T = H2G(presentationContext) - let T = H2G.hashToGroup(presentationContext, domainSeparationString: Data(("HashToGroup-" + ARC.domain + "Tag").utf8)) + let T = H2G.hashToGroup(presentationContext, domainSeparationString: Data(("HashToGroup-" + ciphersuite.domain + "Tag").utf8)) // Recompute m1Tag = H2G(presentationContext) - nonce * tag var m1Tag = T for _ in 0..(label: ARC.domain + ARC.domain + "CredentialPresentation") + var verifier = Verifier(label: ciphersuite.domain + ciphersuite.domain + "CredentialPresentation") let m1Var = verifier.appendScalar(label: "m1") let zVar = verifier.appendScalar(label: "z") let rNegVar = verifier.appendScalar(label: "-r") diff --git a/Sources/_CryptoExtras/ARC/ARCRequest.swift b/Sources/_CryptoExtras/ARC/ARCRequest.swift index 25bf7c55b..c68cb9e43 100644 --- a/Sources/_CryptoExtras/ARC/ARCRequest.swift +++ b/Sources/_CryptoExtras/ARC/ARCRequest.swift @@ -26,12 +26,12 @@ extension ARC { let m2Enc: Group.Element let proof: Proof - init(clientSecrets: ClientSecrets, generatorG: Group.Element, generatorH: Group.Element) throws { + init(clientSecrets: ClientSecrets, generatorG: Group.Element, generatorH: Group.Element, ciphersuite: Ciphersuite) throws { let m1Enc = clientSecrets.m1 * generatorG + clientSecrets.r1 * generatorH let m2Enc = clientSecrets.m2 * generatorG + clientSecrets.r2 * generatorH // Create a prover, and allocate variables for the constrained scalars. - var prover = Prover(label: ARC.domain + ARC.domain + "CredentialRequest") + var prover = Prover(label: ciphersuite.domain + ciphersuite.domain + "CredentialRequest") let m1Var = prover.appendScalar(label: "m1", assignment: clientSecrets.m1) let m2Var = prover.appendScalar(label: "m2", assignment: clientSecrets.m2) let r1Var = prover.appendScalar(label: "r1", assignment: clientSecrets.r1) @@ -50,7 +50,7 @@ extension ARC { self.proof = proof } - func verify(generatorG: Group.Element, generatorH: Group.Element) throws -> Bool { + func verify(generatorG: Group.Element, generatorH: Group.Element, ciphersuite: Ciphersuite) throws -> Bool { // Check that the encrypted attributes were generated with nonzero `m` and `r` values. if (self.m1Enc == generatorG || self.m1Enc == generatorH || self.m1Enc == self.m1Enc + self.m1Enc) || (self.m2Enc == generatorG || self.m2Enc == generatorH || self.m2Enc == self.m2Enc + self.m2Enc) { @@ -58,7 +58,7 @@ extension ARC { } // Create a verifier, and allocate variables for the constrained scalars. - var verifier = Verifier(label: ARC.domain + ARC.domain + "CredentialRequest") + var verifier = Verifier(label: ciphersuite.domain + ciphersuite.domain + "CredentialRequest") let m1Var = verifier.appendScalar(label: "m1") let m2Var = verifier.appendScalar(label: "m2") let r1Var = verifier.appendScalar(label: "r1") diff --git a/Sources/_CryptoExtras/ARC/ARCResponse.swift b/Sources/_CryptoExtras/ARC/ARCResponse.swift index cf0e3e13f..eff747dd3 100644 --- a/Sources/_CryptoExtras/ARC/ARCResponse.swift +++ b/Sources/_CryptoExtras/ARC/ARCResponse.swift @@ -48,7 +48,8 @@ extension ARC { serverPublicKey: ServerPublicKey, generatorG: Group.Element, generatorH: Group.Element, - b: Group.Scalar = Group.Scalar.random + b: Group.Scalar = Group.Scalar.random, + ciphersuite: Ciphersuite ) throws { let U = b * generatorG let X0Aux = b * serverPrivateKey.x0Blinding * generatorH @@ -61,7 +62,7 @@ extension ARC { let encUPrime = b * (serverPublicKey.X0 + serverPrivateKey.x1 * request.m1Enc + serverPrivateKey.x2 * request.m2Enc) // Create a prover, and allocate variables for the constrained scalars. - var prover = Prover(label: ARC.domain + ARC.domain + "CredentialResponse") + var prover = Prover(label: ciphersuite.domain + ciphersuite.domain + "CredentialResponse") let x0Var = prover.appendScalar(label: "x0", assignment: serverPrivateKey.x0) let x1Var = prover.appendScalar(label: "x1", assignment: serverPrivateKey.x1) let x2Var = prover.appendScalar(label: "x2", assignment: serverPrivateKey.x2) @@ -95,15 +96,14 @@ extension ARC { self.proof = proof } - func verify(request: CredentialRequest, serverPublicKey: ServerPublicKey, generatorG: Group.Element, generatorH: Group.Element - ) throws -> Bool { + func verify(request: CredentialRequest, serverPublicKey: ServerPublicKey, generatorG: Group.Element, generatorH: Group.Element, ciphersuite: Ciphersuite) throws -> Bool { // Check that U, encUPrime are not 0 if (self.U == self.U + self.U) || (self.encUPrime == self.encUPrime + self.encUPrime) { return false } // Create a verifier, and allocate variables for the constrained scalars. - var verifier = Verifier(label: ARC.domain + ARC.domain + "CredentialResponse") + var verifier = Verifier(label: ciphersuite.domain + ciphersuite.domain + "CredentialResponse") let x0Var = verifier.appendScalar(label: "x0") let x1Var = verifier.appendScalar(label: "x1") let x2Var = verifier.appendScalar(label: "x2") diff --git a/Sources/_CryptoExtras/ARC/ARCServer.swift b/Sources/_CryptoExtras/ARC/ARCServer.swift index 0565536bf..da7c60629 100644 --- a/Sources/_CryptoExtras/ARC/ARCServer.swift +++ b/Sources/_CryptoExtras/ARC/ARCServer.swift @@ -68,7 +68,7 @@ extension ARC { func respond(credentialRequest: CredentialRequest, b: Group.Scalar = Group.Scalar.random) throws -> CredentialResponse { guard - try credentialRequest.verify(generatorG: generatorG, generatorH: generatorH) + try credentialRequest.verify(generatorG: generatorG, generatorH: generatorH, ciphersuite: self.ciphersuite) else { throw ARC.Errors.invalidProof } @@ -78,12 +78,13 @@ extension ARC { serverPublicKey: self.serverPublicKey, generatorG: generatorG, generatorH: generatorH, - b: b + b: b, + ciphersuite: self.ciphersuite ) } func verify(presentation: Presentation, requestContext: Data, presentationContext: Data, presentationLimit: Int, nonce: Int) throws -> Bool { - let m2 = try H2G.hashToScalar(requestContext, domainSeparationString: Data((ARC.domain + "requestContext").utf8)) + let m2 = try H2G.hashToScalar(requestContext, domainSeparationString: Data((self.ciphersuite.domain + "requestContext").utf8)) return try presentation.verify( serverPrivateKey: self.serverPrivateKey, X1: self.serverPublicKey.X1, @@ -92,7 +93,8 @@ extension ARC { presentationLimit: presentationLimit, nonce: nonce, generatorG: generatorG, - generatorH: generatorH + generatorH: generatorH, + ciphersuite: self.ciphersuite ) } } diff --git a/Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift b/Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift index ddc22dc56..2a6f0f88b 100644 --- a/Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift +++ b/Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift @@ -18,17 +18,24 @@ import XCTest @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) final class ARCAPITests: XCTestCase { + @available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") func testVectors() throws { let data = ARCEncodedTestVector.data(using: .utf8)! let decoder = JSONDecoder() - for vector in try decoder.decode([ARCTestVector].self, from: data) { - try testVector(vector) + let vectors = try decoder.decode([ARCTestVector].self, from: data) + XCTAssert(vectors.count > 0, "No test vectors found") + for vector in vectors { + switch vector.suite { + case "ARCV1-P256": try testVector(vector, using: P256.self) + case "ARCV1-P384": try testVector(vector, using: P384.self) + default: XCTFail("Test vector suite not supported: \(vector.suite)") + } } } - func testVector(_ vector: ARCTestVector) throws { + fileprivate func testVector(_ vector: ARCTestVector, using _: Curve.Type = Curve.self) throws { // [Issuer] Create the server secrets. - let privateKey = try P384._ARCV1.PrivateKey(rawRepresentation: Data( + let privateKey = try Curve._ARCV1.PrivateKey(rawRepresentation: Data( hexString: vector.ServerKey.x0 + vector.ServerKey.x1 + vector.ServerKey.x2 + vector.ServerKey.xb )) @@ -52,14 +59,14 @@ final class ARCAPITests: XCTestCase { _ = (publicKeyBytes, requestContext, presentationContext, presentationLimit) // [Client] Obtain public key out of band (other serializations may be available). - let publicKey = try P384._ARCV1.PublicKey(rawRepresentation: publicKeyBytes) + let publicKey = try Curve._ARCV1.PublicKey(rawRepresentation: publicKeyBytes) // [Client] Prepare a credential request using fixed values from test vector. let precredential = try publicKey.prepareCredentialRequest( requestContext: requestContext, - m1: P384._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.m1)), - r1: P384._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.r1)), - r2: P384._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.r2)) + m1: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.m1)), + r1: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.r1)), + r2: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.r2)) ) // [Client -> Issuer] Send the credential request. @@ -67,17 +74,17 @@ final class ARCAPITests: XCTestCase { // [CHECK] Credential request scalars match test vector. XCTAssertEqual( - credentialRequestBytes[..<(2 * P384.compressedx962PointByteCount)].hexString, + credentialRequestBytes[..<(2 * Curve.compressedx962PointByteCount)].hexString, vector.CredentialRequest.m1_enc + vector.CredentialRequest.m2_enc ) // [Issuer] Receive the credential request. - let credentialRequest = try P384._ARCV1.CredentialRequest(rawRepresentation: credentialRequestBytes) + let credentialRequest = try Curve._ARCV1.CredentialRequest(rawRepresentation: credentialRequestBytes) // [Issuer] Generate a credential response with fixed value from test vector. let credentialResponse = try privateKey.issue( credentialRequest, - b: P384._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialResponse.b)) + b: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialResponse.b)) ) // [Issuer -> Client] Send the credential response. @@ -85,7 +92,7 @@ final class ARCAPITests: XCTestCase { // [CHECK] Credential response scalars match test vector, excluding proof. XCTAssertEqual( - credentialResponseBytes[..<(6 * P384.compressedx962PointByteCount)].hexString, + credentialResponseBytes[..<(6 * Curve.compressedx962PointByteCount)].hexString, vector.CredentialResponse.U + vector.CredentialResponse.enc_U_prime + vector.CredentialResponse.X0_aux @@ -95,7 +102,7 @@ final class ARCAPITests: XCTestCase { ) // [Client] Receive the credential response. - let _ = try P384._ARCV1.CredentialResponse(rawRepresentation: credentialResponseBytes) + let _ = try Curve._ARCV1.CredentialResponse(rawRepresentation: credentialResponseBytes) // [Client] Generate a credential. var credential = try publicKey.finalize(credentialResponse, for: precredential) @@ -111,9 +118,9 @@ final class ARCAPITests: XCTestCase { context: presentationContext, presentationLimit: presentationLimit, fixedNonce: Int(vector.Presentation1.nonce.dropFirst(2), radix: 16)!, - a: P384._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.a)), - r: P384._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.r)), - z: P384._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.z)) + a: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.a)), + r: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.r)), + z: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.z)) ) // NOTE: The presentation proof depends on randomly generated blinding factors. This layer doesn't expose @@ -135,14 +142,14 @@ final class ARCAPITests: XCTestCase { // [CHECK]: Serialization of presentation (ecluding proof) matches spec. XCTAssertEqual( - presentation.rawRepresentation[..<(4 * P384.compressedx962PointByteCount)].hexString, + presentation.rawRepresentation[..<(4 * Curve.compressedx962PointByteCount)].hexString, vector.Presentation1.U + vector.Presentation1.U_prime_commit + vector.Presentation1.m1_commit + vector.Presentation1.tag ) XCTAssertEqual( - presentation.rawRepresentation[(4 * P384.compressedx962PointByteCount)...].hexString.count, + presentation.rawRepresentation[(4 * Curve.compressedx962PointByteCount)...].hexString.count, vector.Presentation1.proof.count ) @@ -155,12 +162,12 @@ final class ARCAPITests: XCTestCase { + vector.Presentation1.proof ) XCTAssertEqual( - try P384._ARCV1.Presentation(rawRepresentation: testVectorPresentationBytes).rawRepresentation.hexString, + try Curve._ARCV1.Presentation(rawRepresentation: testVectorPresentationBytes).rawRepresentation.hexString, testVectorPresentationBytes.hexString ) // [Verifier] Receive the presentation (and the nonce, out of band). - let receivedPresentation = try P384._ARCV1.Presentation(rawRepresentation: testVectorPresentationBytes) + let receivedPresentation = try Curve._ARCV1.Presentation(rawRepresentation: testVectorPresentationBytes) let nonce = Int(vector.Presentation1.nonce.dropFirst(2), radix: 16)! // [Verifier] Verify the presentation. @@ -174,3 +181,172 @@ final class ARCAPITests: XCTestCase { XCTAssertTrue(validPresentation) } } + +// MARK: - Fileprivate protocols to create a unified test over the ARC curves. + +fileprivate protocol ARCCredentialRequest { + init(rawRepresentation: some DataProtocol) throws + var rawRepresentation: Data { get } +} + +fileprivate protocol ARCCredentialResponse { + init(rawRepresentation: some DataProtocol) throws + var rawRepresentation: Data { get } +} + +@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) +fileprivate protocol ARCPresentation { + associatedtype H2G: HashToGroup + var backing: ARC.Presentation { get } + init(rawRepresentation: some DataProtocol) throws + var rawRepresentation: Data { get } +} + +@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) +fileprivate protocol ARCCredential { + associatedtype H2G: HashToGroup + associatedtype Presentation: ARCPresentation + var backing: ARC.Credential { get } + mutating func makePresentation( + context: some DataProtocol, + presentationLimit: Int, + fixedNonce: Int?, + a: H2G.G.Scalar, + r: H2G.G.Scalar, + z: H2G.G.Scalar + ) throws -> (presentation: Presentation, nonce: Int) + mutating func makePresentation(context: some DataProtocol, presentationLimit: Int) throws -> (presentation: Presentation, nonce: Int) +} + +@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) +fileprivate protocol ARCPrivateKey { + associatedtype H2G: HashToGroup + associatedtype Credential + associatedtype PublicKey: ARCPublicKey + associatedtype CredentialRequest: ARCCredentialRequest + associatedtype CredentialResponse: ARCCredentialResponse + associatedtype Presentation: ARCPresentation + init(rawRepresentation: some DataProtocol) throws + var rawRepresentation: Data { get } + var publicKey: PublicKey { get } + func issue(_ credentialRequest: CredentialRequest, b: H2G.G.Scalar) throws -> CredentialResponse + func verify( + _: Presentation, + requestContext: some DataProtocol, + presentationContext: some DataProtocol, + presentationLimit: Int, + nonce: Int + ) throws -> Bool +} + +@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) +fileprivate protocol ARCPublicKey { + associatedtype H2G: HashToGroup + associatedtype Precredential: ARCPrecredential + associatedtype CredentialResponse: ARCCredentialResponse + associatedtype Credential: ARCCredential + init(rawRepresentation: some DataProtocol) throws + var rawRepresentation: Data { get } + func prepareCredentialRequest(requestContext: some DataProtocol, m1: H2G.G.Scalar, r1: H2G.G.Scalar, r2: H2G.G.Scalar) throws -> Precredential + func prepareCredentialRequest(requestContext: some DataProtocol) throws -> Precredential + func finalize(_ credentialResponse: CredentialResponse, for precredential: Precredential) throws -> Credential +} + +fileprivate protocol ARCPrecredential { + associatedtype CredentialRequest: ARCCredentialRequest + var credentialRequest: CredentialRequest { get } +} + +@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) +fileprivate protocol ARCV1 { + associatedtype H2G: HashToGroup + associatedtype CredentialRequest: ARCCredentialRequest + associatedtype CredentialResponse: ARCCredentialResponse + associatedtype Presentation: ARCPresentation + associatedtype Credential: ARCCredential + associatedtype PrivateKey: ARCPrivateKey + associatedtype PublicKey: ARCPublicKey +} + +@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) +fileprivate protocol ARCCurve: OpenSSLSupportedNISTCurve { + associatedtype H2G: HashToGroup where H2G == OpenSSLHashToCurve + associatedtype _ARCV1: ARCV1 +} + +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.Precredential: ARCPrecredential {} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.CredentialRequest: ARCCredentialRequest {} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.CredentialResponse: ARCCredentialResponse {} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.Credential: ARCCredential {} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.Presentation: ARCPresentation {} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.PublicKey: ARCPublicKey { + typealias H2G = P256._ARCV1.H2G +} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1.PrivateKey: ARCPrivateKey {} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256._ARCV1: ARCV1 {} +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P256: ARCCurve {} + + +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1.Precredential: ARCPrecredential {} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1.CredentialRequest: ARCCredentialRequest {} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1.CredentialResponse: ARCCredentialResponse {} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1.Credential: ARCCredential {} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1.Presentation: ARCPresentation {} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1.PublicKey: ARCPublicKey { + typealias H2G = P384._ARCV1.H2G +} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1.PrivateKey: ARCPrivateKey {} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384._ARCV1: ARCV1 {} +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +extension P384: ARCCurve {} + + +// Swift 5.10 compiler needs a little more help to infer the conformances. +#if swift(<6.0) +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +fileprivate extension P256._ARCV1.PrivateKey { + typealias H2G = P256._ARCV1.H2G + typealias Credential = P256._ARCV1.Credential + typealias PublicKey = P256._ARCV1.PublicKey + typealias CredentialRequest = P256._ARCV1.CredentialRequest + typealias CredentialResponse = P256._ARCV1.CredentialResponse + typealias Presentation = P256._ARCV1.Presentation +} + +@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") +@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) +fileprivate extension P384._ARCV1.PrivateKey { + typealias H2G = P384._ARCV1.H2G + typealias Credential = P384._ARCV1.Credential + typealias PublicKey = P384._ARCV1.PublicKey + typealias CredentialRequest = P384._ARCV1.CredentialRequest + typealias CredentialResponse = P384._ARCV1.CredentialResponse + typealias Presentation = P384._ARCV1.Presentation +} +#endif diff --git a/Tests/_CryptoExtrasTests/ARC/ARCEncodingTests.swift b/Tests/_CryptoExtrasTests/ARC/ARCEncodingTests.swift index a02a84716..c65a6aa24 100644 --- a/Tests/_CryptoExtrasTests/ARC/ARCEncodingTests.swift +++ b/Tests/_CryptoExtrasTests/ARC/ARCEncodingTests.swift @@ -17,30 +17,35 @@ import Crypto @available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) class ARCEncodingTests: XCTestCase { - func testserverPublicKeyEncoding() throws { - let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) + func serverPublicKeyEncoding(CurveType _: Curve.Type) throws { + let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) let server = ARC.Server(ciphersuite: ciphersuite) let publicKey = server.serverPublicKey - let publicKeyData = publicKey.serialize() - let publicKey2 = try ARC.ServerPublicKey.deserialize(serverPublicKeyData: publicKeyData) + let publicKeyData = publicKey.serialize(ciphersuite: ciphersuite) + let publicKey2 = try ARC.ServerPublicKey.deserialize(serverPublicKeyData: publicKeyData, ciphersuite: ciphersuite) XCTAssert(publicKey.X0 == publicKey2.X0) XCTAssert(publicKey.X1 == publicKey2.X1) XCTAssert(publicKey.X2 == publicKey2.X2) - let publicKeyData2 = publicKey2.serialize() + let publicKeyData2 = publicKey2.serialize(ciphersuite: ciphersuite) XCTAssertEqual(publicKeyData, publicKeyData2) } - func testRequestEncoding() throws { - let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) + func testServerPublicKeyEncoding() throws { + try serverPublicKeyEncoding(CurveType: P256.self) + try serverPublicKeyEncoding(CurveType: P384.self) + } + + func requestEncoding(CurveType _: Curve.Type) throws { + let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) let server = ARC.Server(ciphersuite: ciphersuite) let requestContext = Data("test request context".utf8) let precredential = try ARC.Precredential(ciphersuite: ciphersuite, requestContext: requestContext, serverPublicKey: server.serverPublicKey) let request = precredential.credentialRequest - let requestData = request.serialize() - let request2 = try ARC.CredentialRequest.deserialize(requestData: requestData) + let requestData = request.serialize(ciphersuite: ciphersuite) + let request2 = try ARC.CredentialRequest.deserialize(requestData: requestData, ciphersuite: ciphersuite) XCTAssert(request.m1Enc == request2.m1Enc) XCTAssert(request.m2Enc == request2.m2Enc) XCTAssert(request.proof.challenge == request2.proof.challenge) @@ -48,20 +53,25 @@ class ARCEncodingTests: XCTestCase { XCTAssert(response == request2.proof.responses[index]) } - let requestData2 = request2.serialize() + let requestData2 = request2.serialize(ciphersuite: ciphersuite) XCTAssertEqual(requestData, requestData2) } - func testResponseEncoding() throws { - let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) + func testRequestEncoding() throws { + try requestEncoding(CurveType: P256.self) + try requestEncoding(CurveType: P384.self) + } + + func responseEncoding(CurveType _: Curve.Type) throws { + let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) let server = ARC.Server(ciphersuite: ciphersuite) let requestContext = Data("test request context".utf8) let precredential = try ARC.Precredential(ciphersuite: ciphersuite, requestContext: requestContext, serverPublicKey: server.serverPublicKey) let request = precredential.credentialRequest let response = try server.respond(credentialRequest: request) - let responseData = response.serialize() - let response2 = try ARC.CredentialResponse.deserialize(responseData: responseData) + let responseData = response.serialize(ciphersuite: ciphersuite) + let response2 = try ARC.CredentialResponse.deserialize(responseData: responseData, ciphersuite: ciphersuite) XCTAssert(response.U == response2.U) XCTAssert(response.encUPrime == response2.encUPrime) XCTAssert(response.X0Aux == response2.X0Aux) @@ -73,12 +83,17 @@ class ARCEncodingTests: XCTestCase { XCTAssert(response == response2.proof.responses[index]) } - let responseData2 = response2.serialize() + let responseData2 = response2.serialize(ciphersuite: ciphersuite) XCTAssertEqual(responseData, responseData2) } - func testCredentialEncoding() throws { - let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) + func testResponseEncoding() throws { + try responseEncoding(CurveType: P256.self) + try responseEncoding(CurveType: P384.self) + } + + func credentialEncoding(CurveType _: Curve.Type) throws { + let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) let server = ARC.Server(ciphersuite: ciphersuite) let requestContext = Data("test request context".utf8) let precredential = try ARC.Precredential(ciphersuite: ciphersuite, requestContext: requestContext, serverPublicKey: server.serverPublicKey) @@ -86,8 +101,8 @@ class ARCEncodingTests: XCTestCase { let response = try server.respond(credentialRequest: request) let credential = try precredential.makeCredential(credentialResponse: response) - let credentialData = try credential.serialize() - let credential2 = try ARC.Credential.deserialize(credentialData: credentialData) + let credentialData = try credential.serialize(ciphersuite: ciphersuite) + let credential2 = try ARC.Credential.deserialize(credentialData: credentialData, ciphersuite: ciphersuite) XCTAssert(credential.m1 == credential2.m1) XCTAssert(credential.U == credential2.U) XCTAssert(credential.UPrime == credential2.UPrime) @@ -99,12 +114,17 @@ class ARCEncodingTests: XCTestCase { XCTAssertEqual(value.1, credential2.presentationState.state[key]?.1) } - let credentialData2 = try credential2.serialize() + let credentialData2 = try credential2.serialize(ciphersuite: ciphersuite) XCTAssertEqual(credentialData, credentialData2) } - func testPresentationEncoding() throws { - let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) + func testCredentialEncoding() throws { + try credentialEncoding(CurveType: P256.self) + try credentialEncoding(CurveType: P384.self) + } + + func presentationEncoding(CurveType _: Curve.Type) throws { + let ciphersuite = ARC.Ciphersuite(HashToCurveImpl.self) let server = ARC.Server(ciphersuite: ciphersuite) let requestContext = Data("test request context".utf8) let precredential = try ARC.Precredential(ciphersuite: ciphersuite, requestContext: requestContext, serverPublicKey: server.serverPublicKey) @@ -113,8 +133,8 @@ class ARCEncodingTests: XCTestCase { var credential = try precredential.makeCredential(credentialResponse: response) let (presentation, _) = try credential.makePresentation(presentationContext: Data("test presentation context".utf8), presentationLimit: 1) - let presentationData = presentation.serialize() - let presentation2 = try ARC.Presentation.deserialize(presentationData: presentationData) + let presentationData = presentation.serialize(ciphersuite: ciphersuite) + let presentation2 = try ARC.Presentation.deserialize(presentationData: presentationData, ciphersuite: ciphersuite) XCTAssert(presentation.U == presentation2.U) XCTAssert(presentation.UPrimeCommit == presentation2.UPrimeCommit) XCTAssert(presentation.m1Commit == presentation2.m1Commit) @@ -124,10 +144,15 @@ class ARCEncodingTests: XCTestCase { XCTAssert(response == presentation2.proof.responses[index]) } - let presentationData2 = presentation2.serialize() + let presentationData2 = presentation2.serialize(ciphersuite: ciphersuite) XCTAssertEqual(presentationData, presentationData2) } + func testPresentationEncoding() throws { + try presentationEncoding(CurveType: P256.self) + try presentationEncoding(CurveType: P384.self) + } + func testPresentationStateEncoding() throws { let emptyPresentationState = ARC.PresentationState() let smallPresentationState = ARC.PresentationState(state: [Data("context1".utf8): (4, [1, 2, 3]), Data("context2".utf8): (10, [4, 5, 6])]) diff --git a/Tests/_CryptoExtrasTests/ARC/ARCPublicAPITests.swift b/Tests/_CryptoExtrasTests/ARC/ARCPublicAPITests.swift index 112e4c1e0..411e1066c 100644 --- a/Tests/_CryptoExtrasTests/ARC/ARCPublicAPITests.swift +++ b/Tests/_CryptoExtrasTests/ARC/ARCPublicAPITests.swift @@ -20,7 +20,7 @@ final class ARCPublicAPITests: XCTestCase { func testARCEndToEnd() throws { // [Issuer] Create the server secrets (other initializers will be available). - let privateKey = P384._ARCV1.PrivateKey() + let privateKey = P256._ARCV1.PrivateKey() // [Issuer] Serialize public key to share with client (other serializations may be available). let publicKeyBytes = privateKey.publicKey.rawRepresentation @@ -35,7 +35,7 @@ final class ARCPublicAPITests: XCTestCase { _ = (publicKeyBytes, requestContext, presentationContext, presentationLimit) // [Client] Obtain public key out of band (other serializations may be available). - let publicKey = try P384._ARCV1.PublicKey(rawRepresentation: publicKeyBytes) + let publicKey = try P256._ARCV1.PublicKey(rawRepresentation: publicKeyBytes) // [Client] Prepare a credential request. let precredential = try publicKey.prepareCredentialRequest(requestContext: requestContext) @@ -44,7 +44,7 @@ final class ARCPublicAPITests: XCTestCase { let credentialRequestBytes = precredential.credentialRequest.rawRepresentation // [Issuer] Receive the credential request. - let credentialRequest = try P384._ARCV1.CredentialRequest(rawRepresentation: credentialRequestBytes) + let credentialRequest = try P256._ARCV1.CredentialRequest(rawRepresentation: credentialRequestBytes) // [Issuer] Generate a credential response. let credentialResponse = try privateKey.issue(credentialRequest) @@ -53,7 +53,7 @@ final class ARCPublicAPITests: XCTestCase { let credentialResponseBytes = credentialResponse.rawRepresentation // [Client] Receive the credential response. - let _ = try P384._ARCV1.CredentialResponse(rawRepresentation: credentialResponseBytes) + let _ = try P256._ARCV1.CredentialResponse(rawRepresentation: credentialResponseBytes) // [Client] Generate a credential. // NOTE: This is a var because it enforces the presentation limits for each presentation prefix. @@ -70,7 +70,7 @@ final class ARCPublicAPITests: XCTestCase { let presentationBytes = presentation.rawRepresentation // [Verifier] Receive the presentation. - let _ = try P384._ARCV1.Presentation(rawRepresentation: presentationBytes) + let _ = try P256._ARCV1.Presentation(rawRepresentation: presentationBytes) // [Verifier] Verify the presentation. let validPresentation = try privateKey.verify( @@ -87,7 +87,7 @@ final class ARCPublicAPITests: XCTestCase { } func testCrendentialEnforcesPresentationLimitLocally() throws { - let privateKey = P384._ARCV1.PrivateKey() + let privateKey = P256._ARCV1.PrivateKey() let publicKey = privateKey.publicKey let requestContext = Data("shared request context".utf8) let presentationContext = Data("shared presentation context".utf8) diff --git a/Tests/_CryptoExtrasTests/ARC/ARCTestVectors.swift b/Tests/_CryptoExtrasTests/ARC/ARCTestVectors.swift index d5fefcca8..b8b43556d 100644 --- a/Tests/_CryptoExtrasTests/ARC/ARCTestVectors.swift +++ b/Tests/_CryptoExtrasTests/ARC/ARCTestVectors.swift @@ -17,6 +17,68 @@ import XCTest let ARCEncodedTestVector = """ [ + { + "Credential": { + "U": "033ee1ebbcff622bc26b10932ed1eb147226d832048fb2337dc0ad7722cb07483d", + "U_prime": "02637fe04cc143281ee607bd8f898e670293dce44a2840b9cbb9e0d1fc7a2b29b4", + "X1": "03c413230a9bd956718aa46138a33f774f4c708d61c1d6400d404243049d4a31dc", + "m1": "eedfe7939e2382934ab5b0f76aae44124955d2c5ebf9b41d88786259c34692d2" + }, + "CredentialRequest": { + "m1": "eedfe7939e2382934ab5b0f76aae44124955d2c5ebf9b41d88786259c34692d2", + "m1_enc": "03b8f11506a5302424143573e087fa20195cb5e893a67ef354eae3a78e263c54e4", + "m2": "911fb315257d9ae29d47ecb48c6fa27074dee6860a0489f8db6ac9a486be6a3e", + "m2_enc": "03f1ae4d7b78ba8030bd63859d4f4a909395c52bda34716b6620a2fdd52b336fc9", + "proof": "0f361327abbc724ff0d37db365065bc4bd60e18125842bb4c03a7e5a632a1e95e74dcc440fcb9fb39106922e0d2544e6c82ca710abf35e8b10bf5d61296c9adb7d683eaed9a76a755b73f2b4b6e763a7c7883ce4b5c21bd02cd96b9af18cfb227f1acb4ead77c85049d291ed7841405610843f163e9cc2f6a8869111582324cd32bf13000c129d274ccf5386cb90e839916d5dff7eade18e3eabec415f613911", + "r1": "008035081690bfde3b1e68b91443c22cc791d244340fe957d5aa44d7313740df", + "r2": "d59c5e6ff560cc597c2b8ca25256c720bceca2ab03921492c5e9e4ad3b558002", + "request_context": "74657374207265717565737420636f6e74657874" + }, + "CredentialResponse": { + "H_aux": "03d3cd09eeb8d19716586a49260c69309c495a717a36cad3381f6c02ac80b70e64", + "U": "033ee1ebbcff622bc26b10932ed1eb147226d832048fb2337dc0ad7722cb07483d", + "X0_aux": "02d453c121324114367906bd11ffc3b6e6a77b75382497279b1a60ab8412c1dec6", + "X1_aux": "03b0e4b1f376c6207bf34efda46ce54b132a20b90bc28b9152f3e441fe2b508b63", + "X2_aux": "0327369efcb7577abaeb7b56940e6e042126900bdf8bd8944c0adbb7be3ad98e2a", + "b": "e699140babbe599f7dd8f6e3e8f615e5f201d1c2b0bc2f821f19e80a0a0e1e7b", + "enc_U_prime": "035b8e09ce8776f1a2c7ef8610c9a6a39936c5666ab8b28d6629d3685056716482", + "proof": "dd4596175db0b4273fcdff330370d2b5e7a4bf92bf518141f4553af37ef0e1260cb8312affc2462800adba102117448b449985d1704d8afd0df9ac708231561dca56faae325cb56b0a9e8ad07bdc6ce90f6e7430090e970a7240e289218de7a17672bea9a66187d102ffef976fb01af69d8d3aa3156a5a4223dc6d08b8ce9f1d2639a2edc7052404bf1410adf6c41465bd687e3dfa5372ea71f804b56d947bae9482e5707f42dbe35f8b0e11b4a0d27a5a01e1b9a75b66d82b7945eb0b002ee400bebcdc4c3133f804b22bd2d771762058cc35a5033365d2e15150fe46d3b0e98e18ee55f0451b0b171420f73592292e4ff50603c1f0d7769dbd090936090f63" + }, + "Presentation1": { + "U": "032704f22133d2ec70f9e6f4bbf64c582220b666f2e2c1d37c3f8995a2a5568c7e", + "U_prime_commit": "03533cf1b2fd53a0716e02425eb42e4c55835aa6b2992d364cba70810d0f8aeb51", + "a": "b78e57df8f0a95d102ff12bbb97e15ed35c23e54f9b4483d30b76772ee60d886", + "m1_commit": "03e412408579105213ed10b6447c85bcd672ba73ecae1e21c463d0df4ef7beb814", + "nonce": "0x0", + "presentation_context": "746573742070726573656e746174696f6e20636f6e74657874", + "proof": "a558da5f17c04adcb0898827aaded14be1dc612dcd12b0579c11bb387ce9ae4b7dbcb3bbe413caaaf754d99e5a342abb7e0041458d670f4b58eda37e745a675295d7a7b86248141d6547b53d793e5c77896ec4dc8dd438ab66d9c8b43ef6b060938a1ca793057b154970ebc3c7ec3a23134e0852d0041f9098ce77311e5b5eca0000000000000000000000000000000000000000000000000000000000000004", + "r": "42252210dd60ddbbf1a57e3b144e26dd693b7644a9626a8c36896ede53d12930", + "tag": "031a774fd87a8f18f6420bea43cf5425e7426eec8ba7b8df5c13dc05f10ec652d9", + "z": "f5a4bbcf14e55e357df9f5ccb5ded37b2b14bc2e1a68e31f86416f0606ee75d1" + }, + "Presentation2": { + "U": "035fd233dee2c147155c6008ea64941b6ff7b315aced12531468f2e27bf22e3ef0", + "U_prime_commit": "02434af337b87fd21d1e3d950aebfc8033a3d2e9dd2bb8b9e7953488078754496d", + "a": "95bcf45150a61f5c44a6cfbf343cd9e0f593f127b6f49bec0f9b20f0550504a2", + "m1_commit": "02a578fd3a84eb5b657367b02de39b45fd48ab7781ef8f94efe601274a5ded2a07", + "nonce": "0x1", + "presentation_context": "746573742070726573656e746174696f6e20636f6e74657874", + "proof": "050965cde906fc4723333b100ce0fd9f7b026315f1db16984d4cccb2bc4aa65eb7a17f5b8dfe4f14d40006506ee5fb323e829dd4cb9dc3c455b2e04dd691600aec3cc3f1939198a80acb78b7f90b3bff769cab890f33e4d69b7c302d21ad35ec457d048d3ed7d13ee82c3c0aac2129ad0c8375cf29cd8ea3948a16b9247b1cc5faf69a3116f903b9dcccc4eff31f026041e49797b53c87eca66cfe1040187ef7", + "r": "d7ed72750b6d366ed0febdc539b52d89434f468a578c59d7ca9015b7da240ad6", + "tag": "03084fe6fff0ecc7c33ef5c49b492dda38083f52e9a2b70b88f3d4b4ba7b50afba", + "z": "91eedfb168c556ff5ca3b89d047f482c9279b47f584aab6c7f895f7674251771" + }, + "ServerKey": { + "X0": "0232b5e93dc2ff489c20a986a84757c5cc4512f057e1ea92011a26d3ad2c56288d", + "X1": "03c413230a9bd956718aa46138a33f774f4c708d61c1d6400d404243049d4a31dc", + "X2": "02db00f6f8e6d235786a120017bd356fe1c9d09069d3ac9352cc9be10ef1505a55", + "x0": "3338fa65ec36e0290022b48eb562889d89dbfa691d1cde91517fa222ed7ad364", + "x1": "f9db001266677f62c095021db018cd8cbb55941d4073698ce45c405d1348b7b1", + "x2": "350e8040f828bf6ceca27405420cdf3d63cb3aef005f40ba51943c8026877963", + "xb": "fd293126bb49a6d793cd77d7db960f5692fec3b7ec07602c60cd32aee595dffd" + }, + "suite": "ARCV1-P256", + }, { "Credential": { "U": "02be890d43908e52ed43ae7bc7098f3a7694617fe44a88c33c6fa4eb9e942c0b2bb9d2fd56a44e1d6094fc7b9e8b949055", @@ -179,9 +241,9 @@ class ARCTestVectors: XCTestCase { // Verify request proof, by creating a new request with the // tv.CredentialRequest.proof scalars and verifying it. - let requestProof = try proofFromString(CurveType: Curve.self, value: tv.CredentialRequest.proof, scalarCount: ARC.CredentialRequest.scalarCount) + let requestProof = try proofFromString(CurveType: Curve.self, value: tv.CredentialRequest.proof, scalarCount: ARC.CredentialRequest>.getScalarCount()) let newRequest = ARC.CredentialRequest(m1Enc: precredential.credentialRequest.m1Enc, m2Enc: precredential.credentialRequest.m2Enc, proof: requestProof) - XCTAssert(try newRequest.verify(generatorG: precredential.generatorG, generatorH: precredential.generatorH)) + XCTAssert(try newRequest.verify(generatorG: precredential.generatorG, generatorH: precredential.generatorH, ciphersuite: ciphersuite)) // Make a credential response, passing in randomness b let b = try scalarFromString(CurveType: Curve.self, value: tv.CredentialResponse.b) @@ -195,9 +257,9 @@ class ARCTestVectors: XCTestCase { // Verify response proof, by creating a new response with the // tv.CredentialResponse.proof scalars and verifying it. - let responseProof = try proofFromString(CurveType: Curve.self, value: tv.CredentialResponse.proof, scalarCount: ARC.CredentialResponse.scalarCount) + let responseProof = try proofFromString(CurveType: Curve.self, value: tv.CredentialResponse.proof, scalarCount: ARC.CredentialResponse>.getScalarCount()) let newResponse = ARC.CredentialResponse(U: response.U, encUPrime: response.encUPrime, X0Aux: response.X0Aux, X1Aux: response.X1Aux, X2Aux: response.X2Aux, HAux: response.HAux, proof: responseProof) - XCTAssert(try newResponse.verify(request: precredential.credentialRequest, serverPublicKey: server.serverPublicKey, generatorG: server.generatorG, generatorH: server.generatorH)) + XCTAssert(try newResponse.verify(request: precredential.credentialRequest, serverPublicKey: server.serverPublicKey, generatorG: server.generatorG, generatorH: server.generatorH, ciphersuite: ciphersuite)) // Make a credential from the response var credential = try precredential.makeCredential(credentialResponse: response) @@ -221,9 +283,9 @@ class ARCTestVectors: XCTestCase { // Verify presentation1 proof, by creating a new presentation with the // tv.Presentation1.proof scalars and verifying it. - let presentation1Proof = try proofFromString(CurveType: Curve.self, value: tv.Presentation1.proof, scalarCount: ARC.Presentation.scalarCount) + let presentation1Proof = try proofFromString(CurveType: Curve.self, value: tv.Presentation1.proof, scalarCount: ARC.Presentation>.getScalarCount()) let newPresentation1 = ARC.Presentation(U: presentation1.U, UPrimeCommit: presentation1.UPrimeCommit, m1Commit: presentation1.m1Commit, tag: presentation1.tag, proof: presentation1Proof) - XCTAssert(try newPresentation1.verify(serverPrivateKey: server.serverPrivateKey, X1: server.serverPublicKey.X1, m2: m2, presentationContext: presentationContext1, presentationLimit: 2, nonce: nonce_1, generatorG: credential.generatorG, generatorH: credential.generatorH)) + XCTAssert(try newPresentation1.verify(serverPrivateKey: server.serverPrivateKey, X1: server.serverPublicKey.X1, m2: m2, presentationContext: presentationContext1, presentationLimit: 2, nonce: nonce_1, generatorG: credential.generatorG, generatorH: credential.generatorH, ciphersuite: ciphersuite)) // Make a second presentation from the credential, passing in randomness a, r, z let presentationContext2 = try Data(hexString: tv.Presentation2.presentation_context) @@ -240,9 +302,9 @@ class ARCTestVectors: XCTestCase { // Verify presentation2 proof, by creating a new presentation with the // tv.Presentation2.proof scalars and verifying it. - let presentation2Proof = try proofFromString(CurveType: Curve.self, value: tv.Presentation2.proof, scalarCount: ARC.Presentation.scalarCount) + let presentation2Proof = try proofFromString(CurveType: Curve.self, value: tv.Presentation2.proof, scalarCount: ARC.Presentation>.getScalarCount()) let newPresentation2 = ARC.Presentation(U: presentation2.U, UPrimeCommit: presentation2.UPrimeCommit, m1Commit: presentation2.m1Commit, tag: presentation2.tag, proof: presentation2Proof) - XCTAssert(try newPresentation2.verify(serverPrivateKey: server.serverPrivateKey, X1: server.serverPublicKey.X1, m2: m2, presentationContext: presentationContext2, presentationLimit: 2, nonce: nonce_2, generatorG: credential.generatorG, generatorH: credential.generatorH)) + XCTAssert(try newPresentation2.verify(serverPrivateKey: server.serverPrivateKey, X1: server.serverPublicKey.X1, m2: m2, presentationContext: presentationContext2, presentationLimit: 2, nonce: nonce_2, generatorG: credential.generatorG, generatorH: credential.generatorH, ciphersuite: ciphersuite)) // Verify both presentations XCTAssertTrue(try server.verify(presentation: presentation1, requestContext: requestContext, presentationContext: presentationContext1, presentationLimit: 2, nonce: nonce_1)) @@ -251,7 +313,8 @@ class ARCTestVectors: XCTestCase { func validateTestVector(_ tv: ARCTestVector) { switch tv.suite { - case ARC.domain: XCTAssertNoThrow(try self.validate(curveType: P384.self, tv)) + case "ARCV1-P256": XCTAssertNoThrow(try self.validate(curveType: P256.self, tv)) + case "ARCV1-P384": XCTAssertNoThrow(try self.validate(curveType: P384.self, tv)) default: XCTFail("Unsupported ciphersuite:" + tv.suite) } } diff --git a/Tests/_CryptoExtrasTests/ARC/ARCTests.swift b/Tests/_CryptoExtrasTests/ARC/ARCTests.swift index b254c7272..d2c4dd8bd 100644 --- a/Tests/_CryptoExtrasTests/ARC/ARCTests.swift +++ b/Tests/_CryptoExtrasTests/ARC/ARCTests.swift @@ -47,7 +47,7 @@ class ARCTests: XCTestCase { XCTAssert(m1Decrypted == m1 * generatorG) let m2Decrypted = request.m2Enc - r2 * generatorH XCTAssert(m2Decrypted == precredential.clientSecrets.m2 * generatorG) - XCTAssert(try request.verify(generatorG: generatorG, generatorH: generatorH)) + XCTAssert(try request.verify(generatorG: generatorG, generatorH: generatorH, ciphersuite: ciphersuite)) // Server receives the CredentialRequest, and makes an CredentialResponse with its server keys. let issuance = try server.respond(credentialRequest: request) @@ -84,7 +84,8 @@ class ARCTests: XCTestCase { presentationLimit: presentationLimit, nonce: nonce1, generatorG: generatorG, - generatorH: generatorH)) + generatorH: generatorH, + ciphersuite: ciphersuite)) // Server verifies Presentation2 with its server keys. XCTAssert(try server.verify( @@ -102,7 +103,8 @@ class ARCTests: XCTestCase { presentationLimit: presentationLimit, nonce: nonce2, generatorG: generatorG, - generatorH: generatorH)) + generatorH: generatorH, + ciphersuite: ciphersuite)) // Test that two presentations with the same presentationContext and privateAttribute, // but difference nonces, have different tag elements From af6be725f5c1e7356878d3cc6a8fdb9c764e14c5 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Thu, 3 Jul 2025 16:14:36 -0700 Subject: [PATCH 08/36] CMake: Declare ASN1 dependency (#376) SwiftCrypto depends on SwiftASN1 which is declared in the exports file, but does not try to find the project, resulting in build failures of downstream projects that fail to explicitly call `find_package(SwiftASN1)` before `find_package(SwiftCrypto)`. Generally, it is recommended that project config files use `find_dependency` to search for the dependencies of the project they represent (https://cmake.org/cmake/help/v3.26/module/CMakeFindDependencyMacro.html). If the package is already found, either through `find_package` in the parent project, or through another means, the `find_dependency` call is a no-op. Co-authored-by: Cory Benfield --- cmake/modules/SwiftCryptoConfig.cmake.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/modules/SwiftCryptoConfig.cmake.in b/cmake/modules/SwiftCryptoConfig.cmake.in index 353de7b15..97e65bd6e 100644 --- a/cmake/modules/SwiftCryptoConfig.cmake.in +++ b/cmake/modules/SwiftCryptoConfig.cmake.in @@ -13,5 +13,7 @@ ##===----------------------------------------------------------------------===## if(NOT TARGET SwiftCrypto) + include(CMakeFindDependencyMacro) + find_dependency(SwiftASN1) include(@SWIFT_CRYPTO_EXPORTS_FILE@) endif() From 871f95d0ebaafb76626d41cc19ebbc81baf29d70 Mon Sep 17 00:00:00 2001 From: Tim Condon <0xTim@users.noreply.github.com> Date: Mon, 7 Jul 2025 13:23:11 +0100 Subject: [PATCH 09/36] Typealias CryptoKitError (#285) Provides a typealias for `CryptoKitError` to hide the implementation detail of CryptoKit. Resolves #274 ### Motivation: CryptoKit is an implementation detail on Apple platforms - this makes it clearer for users coming from other platforms ### Modifications: Added a type alias and updated documentation Co-authored-by: Cory Benfield --- README.md | 2 +- Sources/Crypto/CMakeLists.txt | 1 + Sources/Crypto/CryptoError_boring.swift | 18 ++++++++++++++ .../MLDSA/MLDSA_boring.swift.gyb | 8 +++---- .../_CryptoExtras/MLKEM/MLKEM_boring.swift | 24 +++++++++---------- .../MLKEM/MLKEM_boring.swift.gyb | 12 +++++----- .../_CryptoExtras/RSA/RSA+BlindSigning.swift | 4 ++-- 7 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 Sources/Crypto/CryptoError_boring.swift diff --git a/README.md b/README.md index 6c7e8572a..fd2ca72de 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ What this means for you is that you should depend on Swift Crypto with a version In SwiftPM that can be easily done specifying for example `from: "1.0.0"` meaning that you support Swift Crypto in every version starting from 1.0.0 up to (excluding) 2.0.0. SemVer and Swift Crypto's Public API guarantees should result in a working program without having to worry about testing every single version for compatibility. -Swift Crypto 2.0.0 was released in September 2021. The only breaking change between Swift Crypto 2.0.0 and 1.0.0 was the addition of new cases in the `CryptoKitError` enumeration. For most users, then, it's safe to depend on either the 1.0.0 _or_ 2.0.0 series of releases. +Swift Crypto 2.0.0 was released in September 2021. The only breaking change between Swift Crypto 2.0.0 and 1.0.0 was the addition of new cases in the `CryptoError` enumeration. For most users, then, it's safe to depend on either the 1.0.0 _or_ 2.0.0 series of releases. To do so, please use the following dependency in your `Package.swift`: diff --git a/Sources/Crypto/CMakeLists.txt b/Sources/Crypto/CMakeLists.txt index ec399ffe5..6e9b14e4d 100644 --- a/Sources/Crypto/CMakeLists.txt +++ b/Sources/Crypto/CMakeLists.txt @@ -36,6 +36,7 @@ add_library(Crypto "ASN1/PKCS8PrivateKey.swift" "ASN1/SEC1PrivateKey.swift" "ASN1/SubjectPublicKeyInfo.swift" + "CryptoError_boring.swift" "CryptoKitErrors.swift" "Digests/BoringSSL/Digest_boring.swift" "Digests/Digest.swift" diff --git a/Sources/Crypto/CryptoError_boring.swift b/Sources/Crypto/CryptoError_boring.swift new file mode 100644 index 000000000..685aeb769 --- /dev/null +++ b/Sources/Crypto/CryptoError_boring.swift @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2019-2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) +public typealias CryptoError = CryptoKitError +@available(iOS 14, macOS 11, tvOS 14, watchOS 7, *) +public typealias CryptoASN1Error = CryptoKitASN1Error diff --git a/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb b/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb index 91a86c18d..f38ce4a0a 100644 --- a/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb +++ b/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb @@ -43,7 +43,7 @@ extension MLDSA${parameter_set} { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 32 bytes long. public init(seedRepresentation: some DataProtocol) throws { self.backing = try Backing(seedRepresentation: seedRepresentation) } @@ -119,7 +119,7 @@ extension MLDSA${parameter_set} { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 32 bytes long. init(seedRepresentation: some DataProtocol) throws { guard seedRepresentation.count == MLDSA.seedByteCount else { throw CryptoKitError.incorrectKeySize @@ -199,7 +199,7 @@ extension MLDSA${parameter_set} { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. public init(rawRepresentation: some DataProtocol) throws { self.backing = try Backing(rawRepresentation: rawRepresentation) } @@ -252,7 +252,7 @@ extension MLDSA${parameter_set} { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. init(rawRepresentation: some DataProtocol) throws { guard rawRepresentation.count == MLDSA${parameter_set}.PublicKey.Backing.byteCount else { throw CryptoKitError.incorrectKeySize diff --git a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift b/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift index 28d19733b..70a31b8d4 100644 --- a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift +++ b/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift @@ -46,7 +46,7 @@ extension MLKEM768 { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 64 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. public init(seedRepresentation: some DataProtocol) throws { self.backing = try Backing(seedRepresentation: seedRepresentation) } @@ -65,7 +65,7 @@ extension MLKEM768 { /// /// - Parameter encapsulated: The encapsulated shared secret. /// - /// - Throws: `CryptoKitError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. + /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. /// /// - Returns: The symmetric key. public func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { @@ -104,7 +104,7 @@ extension MLKEM768 { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 64 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. init(seedRepresentation: some DataProtocol) throws { guard seedRepresentation.count == MLKEM.seedByteCount else { throw CryptoKitError.incorrectKeySize @@ -135,7 +135,7 @@ extension MLKEM768 { /// /// - Parameter encapsulated: The encapsulated shared secret. /// - /// - Throws: `CryptoKitError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. + /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. /// /// - Returns: The symmetric key. func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { @@ -184,7 +184,7 @@ extension MLKEM768 { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. public init(rawRepresentation: some DataProtocol) throws { self.backing = try Backing(rawRepresentation: rawRepresentation) } @@ -216,7 +216,7 @@ extension MLKEM768 { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. init(rawRepresentation: some DataProtocol) throws { guard rawRepresentation.count == MLKEM768.PublicKey.byteCount else { throw CryptoKitError.incorrectKeySize @@ -317,7 +317,7 @@ extension MLKEM1024 { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 64 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. public init(seedRepresentation: some DataProtocol) throws { self.backing = try Backing(seedRepresentation: seedRepresentation) } @@ -336,7 +336,7 @@ extension MLKEM1024 { /// /// - Parameter encapsulated: The encapsulated shared secret. /// - /// - Throws: `CryptoKitError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. + /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. /// /// - Returns: The symmetric key. public func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { @@ -375,7 +375,7 @@ extension MLKEM1024 { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 64 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. init(seedRepresentation: some DataProtocol) throws { guard seedRepresentation.count == MLKEM.seedByteCount else { throw CryptoKitError.incorrectKeySize @@ -406,7 +406,7 @@ extension MLKEM1024 { /// /// - Parameter encapsulated: The encapsulated shared secret. /// - /// - Throws: `CryptoKitError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. + /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. /// /// - Returns: The symmetric key. func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { @@ -455,7 +455,7 @@ extension MLKEM1024 { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. public init(rawRepresentation: some DataProtocol) throws { self.backing = try Backing(rawRepresentation: rawRepresentation) } @@ -487,7 +487,7 @@ extension MLKEM1024 { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. init(rawRepresentation: some DataProtocol) throws { guard rawRepresentation.count == MLKEM1024.PublicKey.byteCount else { throw CryptoKitError.incorrectKeySize diff --git a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb b/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb index cfe11c73b..8b1ae5971 100644 --- a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb +++ b/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb @@ -50,7 +50,7 @@ extension MLKEM${parameter_set} { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 64 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. public init(seedRepresentation: some DataProtocol) throws { self.backing = try Backing(seedRepresentation: seedRepresentation) } @@ -69,7 +69,7 @@ extension MLKEM${parameter_set} { /// /// - Parameter encapsulated: The encapsulated shared secret. /// - /// - Throws: `CryptoKitError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. + /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. /// /// - Returns: The symmetric key. public func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { @@ -108,7 +108,7 @@ extension MLKEM${parameter_set} { /// /// - Parameter seedRepresentation: The seed to use to generate the private key. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 64 bytes long. + /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. init(seedRepresentation: some DataProtocol) throws { guard seedRepresentation.count == MLKEM.seedByteCount else { throw CryptoKitError.incorrectKeySize @@ -139,7 +139,7 @@ extension MLKEM${parameter_set} { /// /// - Parameter encapsulated: The encapsulated shared secret. /// - /// - Throws: `CryptoKitError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. + /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. /// /// - Returns: The symmetric key. func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { @@ -188,7 +188,7 @@ extension MLKEM${parameter_set} { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. public init(rawRepresentation: some DataProtocol) throws { self.backing = try Backing(rawRepresentation: rawRepresentation) } @@ -220,7 +220,7 @@ extension MLKEM${parameter_set} { /// /// - Parameter rawRepresentation: The public key bytes. /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. + /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. init(rawRepresentation: some DataProtocol) throws { guard rawRepresentation.count == MLKEM${parameter_set}.PublicKey.byteCount else { throw CryptoKitError.incorrectKeySize diff --git a/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift b/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift index a1d56f23f..a0af91821 100644 --- a/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift +++ b/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift @@ -495,7 +495,7 @@ extension _RSA.BlindSigning.PublicKey { extension _RSA.BlindSigning { /// Errors defined in the RSA Blind Signatures protocol. /// - /// - NOTE: This type does not conform to `Swift.Error`, it is used to construct a `CryptoKitError`. + /// - NOTE: This type does not conform to `Swift.Error`, it is used to construct a `CryptoError`. /// /// - Seealso: [RFC 9474: Errors](https://www.rfc-editor.org/rfc/rfc9474.html#name-errors). @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) @@ -512,7 +512,7 @@ extension _RSA.BlindSigning { @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension CryptoKitError { - /// Map an error from the RSA Blind Signatures protocol to a CryptoKitError. + /// Map an error from the RSA Blind Signatures protocol to a CryptoError. init(_ error: _RSA.BlindSigning.ProtocolError) { switch error { case .messageTooLong: From e5f10a704b9e08cfa45b1cc2ca6baf13d66b3e33 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Tue, 15 Jul 2025 10:02:01 +0100 Subject: [PATCH 10/36] Mention Windows in README (#378) This addresses https://github.com/apple/swift-crypto/issues/369#issuecomment-3067158075 We have passing Windows CI on PRs, so we should update our README to include ARM64 Windows as a supported platform. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fd2ca72de..ec5134552 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Swift Crypto -Swift Crypto is an open-source implementation of a substantial portion of the API of [Apple CryptoKit](https://developer.apple.com/documentation/cryptokit) suitable for use on Linux platforms. It enables cross-platform or server applications with the advantages of CryptoKit. +Swift Crypto is an open-source implementation of a substantial portion of the API of [Apple CryptoKit](https://developer.apple.com/documentation/cryptokit) suitable for use on Linux and ARM64 Windows platforms. It enables cross-platform or server applications with the advantages of CryptoKit. ## Using Swift Crypto @@ -28,7 +28,7 @@ Swift Crypto compiles in two distinct modes depending on the platform for which When building Swift Crypto for use on an Apple platform where CryptoKit is already available, Swift Crypto compiles its entire API surface down to nothing and simply re-exports the API of CryptoKit. This means that when using Apple platforms Swift Crypto simply delegates all work to the core implementation of CryptoKit, as though Swift Crypto was not even there. -When building Swift Crypto for use on Linux, Swift Crypto builds substantially more code. In particular, we build: +When building Swift Crypto for use on Linux or Windows, Swift Crypto builds substantially more code. In particular, we build: 1. A vendored copy of BoringSSL's libcrypto. 2. The common API of Swift Crypto and CryptoKit. From 75475b8063d738195819012407f055f4493795ef Mon Sep 17 00:00:00 2001 From: George Barnett Date: Mon, 21 Jul 2025 15:35:06 +0100 Subject: [PATCH 11/36] Back out changes post-quantum changes for release (#379) --- .../include/CCryptoBoringSSL.h | 2 - Sources/_CryptoExtras/CMakeLists.txt | 3 - Sources/_CryptoExtras/Docs.docc/index.md | 4 - .../_CryptoExtras/MLDSA/MLDSA_boring.swift | 638 ---------- .../MLDSA/MLDSA_boring.swift.gyb | 337 ------ .../_CryptoExtras/MLKEM/MLKEM_boring.swift | 571 --------- .../MLKEM/MLKEM_boring.swift.gyb | 305 ----- .../Util/Optional+withUnsafeBytes.swift | 26 - Tests/_CryptoExtrasTests/MLDSATests.swift | 305 ----- Tests/_CryptoExtrasTests/MLKEMTests.swift | 107 -- .../mldsa_65_verify_test.json | 1026 ----------------- .../mldsa_87_verify_test.json | 947 --------------- .../mldsa_nist_keygen_65_tests.json | 129 --- .../mldsa_nist_keygen_87_tests.json | 129 --- scripts/vendor-boringssl.sh | 2 - 15 files changed, 4531 deletions(-) delete mode 100644 Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift delete mode 100644 Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb delete mode 100644 Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift delete mode 100644 Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb delete mode 100644 Sources/_CryptoExtras/Util/Optional+withUnsafeBytes.swift delete mode 100644 Tests/_CryptoExtrasTests/MLDSATests.swift delete mode 100644 Tests/_CryptoExtrasTests/MLKEMTests.swift delete mode 100644 Tests/_CryptoExtrasVectors/mldsa_65_verify_test.json delete mode 100644 Tests/_CryptoExtrasVectors/mldsa_87_verify_test.json delete mode 100644 Tests/_CryptoExtrasVectors/mldsa_nist_keygen_65_tests.json delete mode 100644 Tests/_CryptoExtrasVectors/mldsa_nist_keygen_87_tests.json diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h index a7bdf1440..3ff3aef59 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h @@ -44,8 +44,6 @@ #include "CCryptoBoringSSL_hrss.h" #include "CCryptoBoringSSL_md4.h" #include "CCryptoBoringSSL_md5.h" -#include "CCryptoBoringSSL_mldsa.h" -#include "CCryptoBoringSSL_mlkem.h" #include "CCryptoBoringSSL_obj_mac.h" #include "CCryptoBoringSSL_objects.h" #include "CCryptoBoringSSL_opensslv.h" diff --git a/Sources/_CryptoExtras/CMakeLists.txt b/Sources/_CryptoExtras/CMakeLists.txt index a9959d7e0..5f9decf1f 100644 --- a/Sources/_CryptoExtras/CMakeLists.txt +++ b/Sources/_CryptoExtras/CMakeLists.txt @@ -45,8 +45,6 @@ add_library(_CryptoExtras "Key Derivation/PBKDF2/PBKDF2.swift" "Key Derivation/Scrypt/BoringSSL/Scrypt_boring.swift" "Key Derivation/Scrypt/Scrypt.swift" - "MLDSA/MLDSA_boring.swift" - "MLKEM/MLKEM_boring.swift" "OPRFs/OPRF.swift" "OPRFs/OPRFClient.swift" "OPRFs/OPRFServer.swift" @@ -63,7 +61,6 @@ add_library(_CryptoExtras "Util/Error.swift" "Util/I2OSP.swift" "Util/IntegerEncoding.swift" - "Util/Optional+withUnsafeBytes.swift" "Util/PEMDocument.swift" "Util/PrettyBytes.swift" "Util/SubjectPublicKeyInfo.swift" diff --git a/Sources/_CryptoExtras/Docs.docc/index.md b/Sources/_CryptoExtras/Docs.docc/index.md index b38a23dd7..50b5eca56 100644 --- a/Sources/_CryptoExtras/Docs.docc/index.md +++ b/Sources/_CryptoExtras/Docs.docc/index.md @@ -15,10 +15,6 @@ Provides additional cryptographic APIs that are not available in CryptoKit (and ### Public key cryptography - ``_RSA`` -- ``MLKEM768`` -- ``MLKEM1024`` -- ``MLDSA65`` -- ``MLDSA87`` ### Key derivation functions diff --git a/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift b/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift deleted file mode 100644 index 51941f563..000000000 --- a/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift +++ /dev/null @@ -1,638 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -// MARK: - Generated file, do NOT edit -// any edits of this file WILL be overwritten and thus discarded -// see section `gyb` in `README` for details. - -@_implementationOnly import CCryptoBoringSSL -import Crypto -import Foundation - -/// A module-lattice-based digital signature algorithm that provides security against quantum computing attacks. -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -public enum MLDSA65 {} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA65 { - /// A ML-DSA-65 private key. - public struct PrivateKey: Sendable { - private var backing: Backing - - /// Initialize a ML-DSA-65 private key from a random seed. - public init() throws { - self.backing = try Backing() - } - - /// Initialize a ML-DSA-65 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long. - public init(seedRepresentation: some DataProtocol) throws { - self.backing = try Backing(seedRepresentation: seedRepresentation) - } - - /// The seed from which this private key was generated. - public var seedRepresentation: Data { - self.backing.seed - } - - /// The public key associated with this private key. - public var publicKey: PublicKey { - self.backing.publicKey - } - - /// Generate a signature for the given data. - /// - /// - Parameter data: The message to sign. - /// - /// - Returns: The signature of the message. - public func signature(for data: D) throws -> Data { - let context: Data? = nil - return try self.backing.signature(for: data, context: context) - } - - /// Generate a signature for the given data. - /// - /// - Parameters: - /// - data: The message to sign. - /// - context: The context to use for the signature. - /// - /// - Returns: The signature of the message. - public func signature(for data: D, context: C) throws -> Data { - try self.backing.signature(for: data, context: context) - } - - /// The size of the private key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - fileprivate var key: MLDSA65_private_key - var seed: Data - - /// Initialize a ML-DSA-65 private key from a random seed. - init() throws { - // We have to initialize all members before `self` is captured by the closure - self.key = .init() - self.seed = Data() - - self.seed = try withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLDSA.seedByteCount - ) { seedPtr in - try withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLDSA65.PublicKey.Backing.byteCount - ) { publicKeyPtr in - guard - CCryptoBoringSSL_MLDSA65_generate_key( - publicKeyPtr.baseAddress, - seedPtr.baseAddress, - &self.key - ) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - - return Data(bytes: seedPtr.baseAddress!, count: MLDSA.seedByteCount) - } - } - } - - /// Initialize a ML-DSA-65 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long. - init(seedRepresentation: some DataProtocol) throws { - guard seedRepresentation.count == MLDSA.seedByteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - self.seed = Data(seedRepresentation) - - guard - self.seed.withUnsafeBytes({ seedPtr in - CCryptoBoringSSL_MLDSA65_private_key_from_seed( - &self.key, - seedPtr.baseAddress, - MLDSA.seedByteCount - ) - }) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - } - - /// The public key associated with this private key. - var publicKey: PublicKey { - PublicKey(privateKeyBacking: self) - } - - /// Generate a signature for the given data. - /// - /// - Parameters: - /// - data: The message to sign. - /// - context: The context to use for the signature. - /// - /// - Returns: The signature of the message. - func signature(for data: D, context: C?) throws -> Data { - var signature = Data(repeating: 0, count: MLDSA65.signatureByteCount) - - let rc: CInt = signature.withUnsafeMutableBytes { signaturePtr in - let bytes: ContiguousBytes = data.regions.count == 1 ? data.regions.first! : Array(data) - return bytes.withUnsafeBytes { dataPtr in - context.withUnsafeBytes { contextPtr in - CCryptoBoringSSL_MLDSA65_sign( - signaturePtr.baseAddress, - &self.key, - dataPtr.baseAddress, - dataPtr.count, - contextPtr.baseAddress, - contextPtr.count - ) - } - } - } - - guard rc == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - - return signature - } - - /// The size of the private key in bytes. - static let byteCount = Int(MLDSA65_PRIVATE_KEY_BYTES) - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA65 { - /// A ML-DSA-65 public key. - public struct PublicKey: Sendable { - private var backing: Backing - - fileprivate init(privateKeyBacking: PrivateKey.Backing) { - self.backing = Backing(privateKeyBacking: privateKeyBacking) - } - - /// Initialize a ML-DSA-65 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. - public init(rawRepresentation: some DataProtocol) throws { - self.backing = try Backing(rawRepresentation: rawRepresentation) - } - - /// The raw binary representation of the public key. - public var rawRepresentation: Data { - self.backing.rawRepresentation - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - public func isValidSignature(_ signature: S, for data: D) -> Bool { - let context: Data? = nil - return self.backing.isValidSignature(signature, for: data, context: context) - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - context: The context to use for the signature verification. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - public func isValidSignature( - _ signature: S, - for data: D, - context: C - ) -> Bool { - self.backing.isValidSignature(signature, for: data, context: context) - } - - /// The size of the public key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - private var key: MLDSA65_public_key - - init(privateKeyBacking: PrivateKey.Backing) { - self.key = .init() - CCryptoBoringSSL_MLDSA65_public_from_private(&self.key, &privateKeyBacking.key) - } - - /// Initialize a ML-DSA-65 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. - init(rawRepresentation: some DataProtocol) throws { - guard rawRepresentation.count == MLDSA65.PublicKey.Backing.byteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - - let bytes: ContiguousBytes = - rawRepresentation.regions.count == 1 - ? rawRepresentation.regions.first! - : Array(rawRepresentation) - try bytes.withUnsafeBytes { rawBuffer in - try rawBuffer.withMemoryRebound(to: UInt8.self) { buffer in - var cbs = CBS(data: buffer.baseAddress, len: buffer.count) - guard CCryptoBoringSSL_MLDSA65_parse_public_key(&self.key, &cbs) == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - } - } - } - - /// The raw binary representation of the public key. - var rawRepresentation: Data { - var cbb = CBB() - // The following BoringSSL functions can only fail on allocation failure, which we define as impossible. - CCryptoBoringSSL_CBB_init(&cbb, MLDSA65.PublicKey.Backing.byteCount) - defer { CCryptoBoringSSL_CBB_cleanup(&cbb) } - CCryptoBoringSSL_MLDSA65_marshal_public_key(&cbb, &self.key) - return Data(bytes: CCryptoBoringSSL_CBB_data(&cbb), count: CCryptoBoringSSL_CBB_len(&cbb)) - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - context: The context to use for the signature verification. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - func isValidSignature( - _ signature: S, - for data: D, - context: C? - ) -> Bool { - let signatureBytes: ContiguousBytes = - signature.regions.count == 1 ? signature.regions.first! : Array(signature) - return signatureBytes.withUnsafeBytes { signaturePtr in - let dataBytes: ContiguousBytes = data.regions.count == 1 ? data.regions.first! : Array(data) - let rc: CInt = dataBytes.withUnsafeBytes { dataPtr in - context.withUnsafeBytes { contextPtr in - CCryptoBoringSSL_MLDSA65_verify( - &self.key, - signaturePtr.baseAddress, - signaturePtr.count, - dataPtr.baseAddress, - dataPtr.count, - contextPtr.baseAddress, - contextPtr.count - ) - } - } - return rc == 1 - } - } - - /// The size of the public key in bytes. - static let byteCount = Int(MLDSA65_PUBLIC_KEY_BYTES) - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA65 { - /// The size of the signature in bytes. - private static let signatureByteCount = Int(MLDSA65_SIGNATURE_BYTES) -} - -/// A module-lattice-based digital signature algorithm that provides security against quantum computing attacks. -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -public enum MLDSA87 {} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA87 { - /// A ML-DSA-87 private key. - public struct PrivateKey: Sendable { - private var backing: Backing - - /// Initialize a ML-DSA-87 private key from a random seed. - public init() throws { - self.backing = try Backing() - } - - /// Initialize a ML-DSA-87 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long. - public init(seedRepresentation: some DataProtocol) throws { - self.backing = try Backing(seedRepresentation: seedRepresentation) - } - - /// The seed from which this private key was generated. - public var seedRepresentation: Data { - self.backing.seed - } - - /// The public key associated with this private key. - public var publicKey: PublicKey { - self.backing.publicKey - } - - /// Generate a signature for the given data. - /// - /// - Parameter data: The message to sign. - /// - /// - Returns: The signature of the message. - public func signature(for data: D) throws -> Data { - let context: Data? = nil - return try self.backing.signature(for: data, context: context) - } - - /// Generate a signature for the given data. - /// - /// - Parameters: - /// - data: The message to sign. - /// - context: The context to use for the signature. - /// - /// - Returns: The signature of the message. - public func signature(for data: D, context: C) throws -> Data { - try self.backing.signature(for: data, context: context) - } - - /// The size of the private key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - fileprivate var key: MLDSA87_private_key - var seed: Data - - /// Initialize a ML-DSA-87 private key from a random seed. - init() throws { - // We have to initialize all members before `self` is captured by the closure - self.key = .init() - self.seed = Data() - - self.seed = try withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLDSA.seedByteCount - ) { seedPtr in - try withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLDSA87.PublicKey.Backing.byteCount - ) { publicKeyPtr in - guard - CCryptoBoringSSL_MLDSA87_generate_key( - publicKeyPtr.baseAddress, - seedPtr.baseAddress, - &self.key - ) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - - return Data(bytes: seedPtr.baseAddress!, count: MLDSA.seedByteCount) - } - } - } - - /// Initialize a ML-DSA-87 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long. - init(seedRepresentation: some DataProtocol) throws { - guard seedRepresentation.count == MLDSA.seedByteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - self.seed = Data(seedRepresentation) - - guard - self.seed.withUnsafeBytes({ seedPtr in - CCryptoBoringSSL_MLDSA87_private_key_from_seed( - &self.key, - seedPtr.baseAddress, - MLDSA.seedByteCount - ) - }) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - } - - /// The public key associated with this private key. - var publicKey: PublicKey { - PublicKey(privateKeyBacking: self) - } - - /// Generate a signature for the given data. - /// - /// - Parameters: - /// - data: The message to sign. - /// - context: The context to use for the signature. - /// - /// - Returns: The signature of the message. - func signature(for data: D, context: C?) throws -> Data { - var signature = Data(repeating: 0, count: MLDSA87.signatureByteCount) - - let rc: CInt = signature.withUnsafeMutableBytes { signaturePtr in - let bytes: ContiguousBytes = data.regions.count == 1 ? data.regions.first! : Array(data) - return bytes.withUnsafeBytes { dataPtr in - context.withUnsafeBytes { contextPtr in - CCryptoBoringSSL_MLDSA87_sign( - signaturePtr.baseAddress, - &self.key, - dataPtr.baseAddress, - dataPtr.count, - contextPtr.baseAddress, - contextPtr.count - ) - } - } - } - - guard rc == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - - return signature - } - - /// The size of the private key in bytes. - static let byteCount = Int(MLDSA87_PRIVATE_KEY_BYTES) - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA87 { - /// A ML-DSA-87 public key. - public struct PublicKey: Sendable { - private var backing: Backing - - fileprivate init(privateKeyBacking: PrivateKey.Backing) { - self.backing = Backing(privateKeyBacking: privateKeyBacking) - } - - /// Initialize a ML-DSA-87 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. - public init(rawRepresentation: some DataProtocol) throws { - self.backing = try Backing(rawRepresentation: rawRepresentation) - } - - /// The raw binary representation of the public key. - public var rawRepresentation: Data { - self.backing.rawRepresentation - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - public func isValidSignature(_ signature: S, for data: D) -> Bool { - let context: Data? = nil - return self.backing.isValidSignature(signature, for: data, context: context) - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - context: The context to use for the signature verification. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - public func isValidSignature( - _ signature: S, - for data: D, - context: C - ) -> Bool { - self.backing.isValidSignature(signature, for: data, context: context) - } - - /// The size of the public key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - private var key: MLDSA87_public_key - - init(privateKeyBacking: PrivateKey.Backing) { - self.key = .init() - CCryptoBoringSSL_MLDSA87_public_from_private(&self.key, &privateKeyBacking.key) - } - - /// Initialize a ML-DSA-87 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size. - init(rawRepresentation: some DataProtocol) throws { - guard rawRepresentation.count == MLDSA87.PublicKey.Backing.byteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - - let bytes: ContiguousBytes = - rawRepresentation.regions.count == 1 - ? rawRepresentation.regions.first! - : Array(rawRepresentation) - try bytes.withUnsafeBytes { rawBuffer in - try rawBuffer.withMemoryRebound(to: UInt8.self) { buffer in - var cbs = CBS(data: buffer.baseAddress, len: buffer.count) - guard CCryptoBoringSSL_MLDSA87_parse_public_key(&self.key, &cbs) == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - } - } - } - - /// The raw binary representation of the public key. - var rawRepresentation: Data { - var cbb = CBB() - // The following BoringSSL functions can only fail on allocation failure, which we define as impossible. - CCryptoBoringSSL_CBB_init(&cbb, MLDSA87.PublicKey.Backing.byteCount) - defer { CCryptoBoringSSL_CBB_cleanup(&cbb) } - CCryptoBoringSSL_MLDSA87_marshal_public_key(&cbb, &self.key) - return Data(bytes: CCryptoBoringSSL_CBB_data(&cbb), count: CCryptoBoringSSL_CBB_len(&cbb)) - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - context: The context to use for the signature verification. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - func isValidSignature( - _ signature: S, - for data: D, - context: C? - ) -> Bool { - let signatureBytes: ContiguousBytes = - signature.regions.count == 1 ? signature.regions.first! : Array(signature) - return signatureBytes.withUnsafeBytes { signaturePtr in - let dataBytes: ContiguousBytes = data.regions.count == 1 ? data.regions.first! : Array(data) - let rc: CInt = dataBytes.withUnsafeBytes { dataPtr in - context.withUnsafeBytes { contextPtr in - CCryptoBoringSSL_MLDSA87_verify( - &self.key, - signaturePtr.baseAddress, - signaturePtr.count, - dataPtr.baseAddress, - dataPtr.count, - contextPtr.baseAddress, - contextPtr.count - ) - } - } - return rc == 1 - } - } - - /// The size of the public key in bytes. - static let byteCount = Int(MLDSA87_PUBLIC_KEY_BYTES) - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA87 { - /// The size of the signature in bytes. - private static let signatureByteCount = Int(MLDSA87_SIGNATURE_BYTES) -} - -private enum MLDSA { - /// The size of the seed in bytes. - fileprivate static let seedByteCount = 32 -} diff --git a/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb b/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb deleted file mode 100644 index f38ce4a0a..000000000 --- a/Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift.gyb +++ /dev/null @@ -1,337 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -// MARK: - Generated file, do NOT edit -// any edits of this file WILL be overwritten and thus discarded -// see section `gyb` in `README` for details. - -@_implementationOnly import CCryptoBoringSSL -import Crypto -import Foundation -%{ - parameter_sets = ["65", "87"] -}% -% for parameter_set in parameter_sets: - -/// A module-lattice-based digital signature algorithm that provides security against quantum computing attacks. -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -public enum MLDSA${parameter_set} {} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA${parameter_set} { - /// A ML-DSA-${parameter_set} private key. - public struct PrivateKey: Sendable { - private var backing: Backing - - /// Initialize a ML-DSA-${parameter_set} private key from a random seed. - public init() throws { - self.backing = try Backing() - } - - /// Initialize a ML-DSA-${parameter_set} private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 32 bytes long. - public init(seedRepresentation: some DataProtocol) throws { - self.backing = try Backing(seedRepresentation: seedRepresentation) - } - - /// The seed from which this private key was generated. - public var seedRepresentation: Data { - self.backing.seed - } - - /// The public key associated with this private key. - public var publicKey: PublicKey { - self.backing.publicKey - } - - /// Generate a signature for the given data. - /// - /// - Parameter data: The message to sign. - /// - /// - Returns: The signature of the message. - public func signature(for data: D) throws -> Data { - let context: Data? = nil - return try self.backing.signature(for: data, context: context) - } - - /// Generate a signature for the given data. - /// - /// - Parameters: - /// - data: The message to sign. - /// - context: The context to use for the signature. - /// - /// - Returns: The signature of the message. - public func signature(for data: D, context: C) throws -> Data { - try self.backing.signature(for: data, context: context) - } - - /// The size of the private key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - fileprivate var key: MLDSA${parameter_set}_private_key - var seed: Data - - /// Initialize a ML-DSA-${parameter_set} private key from a random seed. - init() throws { - // We have to initialize all members before `self` is captured by the closure - self.key = .init() - self.seed = Data() - - self.seed = try withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLDSA.seedByteCount - ) { seedPtr in - try withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLDSA${parameter_set}.PublicKey.Backing.byteCount - ) { publicKeyPtr in - guard - CCryptoBoringSSL_MLDSA${parameter_set}_generate_key( - publicKeyPtr.baseAddress, - seedPtr.baseAddress, - &self.key - ) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - - return Data(bytes: seedPtr.baseAddress!, count: MLDSA.seedByteCount) - } - } - } - - /// Initialize a ML-DSA-${parameter_set} private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 32 bytes long. - init(seedRepresentation: some DataProtocol) throws { - guard seedRepresentation.count == MLDSA.seedByteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - self.seed = Data(seedRepresentation) - - guard - self.seed.withUnsafeBytes({ seedPtr in - CCryptoBoringSSL_MLDSA${parameter_set}_private_key_from_seed( - &self.key, - seedPtr.baseAddress, - MLDSA.seedByteCount - ) - }) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - } - - /// The public key associated with this private key. - var publicKey: PublicKey { - PublicKey(privateKeyBacking: self) - } - - /// Generate a signature for the given data. - /// - /// - Parameters: - /// - data: The message to sign. - /// - context: The context to use for the signature. - /// - /// - Returns: The signature of the message. - func signature(for data: D, context: C?) throws -> Data { - var signature = Data(repeating: 0, count: MLDSA${parameter_set}.signatureByteCount) - - let rc: CInt = signature.withUnsafeMutableBytes { signaturePtr in - let bytes: ContiguousBytes = data.regions.count == 1 ? data.regions.first! : Array(data) - return bytes.withUnsafeBytes { dataPtr in - context.withUnsafeBytes { contextPtr in - CCryptoBoringSSL_MLDSA${parameter_set}_sign( - signaturePtr.baseAddress, - &self.key, - dataPtr.baseAddress, - dataPtr.count, - contextPtr.baseAddress, - contextPtr.count - ) - } - } - } - - guard rc == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - - return signature - } - - /// The size of the private key in bytes. - static let byteCount = Int(MLDSA${parameter_set}_PRIVATE_KEY_BYTES) - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA${parameter_set} { - /// A ML-DSA-${parameter_set} public key. - public struct PublicKey: Sendable { - private var backing: Backing - - fileprivate init(privateKeyBacking: PrivateKey.Backing) { - self.backing = Backing(privateKeyBacking: privateKeyBacking) - } - - /// Initialize a ML-DSA-${parameter_set} public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - public init(rawRepresentation: some DataProtocol) throws { - self.backing = try Backing(rawRepresentation: rawRepresentation) - } - - /// The raw binary representation of the public key. - public var rawRepresentation: Data { - self.backing.rawRepresentation - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - public func isValidSignature(_ signature: S, for data: D) -> Bool { - let context: Data? = nil - return self.backing.isValidSignature(signature, for: data, context: context) - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - context: The context to use for the signature verification. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - public func isValidSignature( - _ signature: S, - for data: D, - context: C - ) -> Bool { - self.backing.isValidSignature(signature, for: data, context: context) - } - - /// The size of the public key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - private var key: MLDSA${parameter_set}_public_key - - init(privateKeyBacking: PrivateKey.Backing) { - self.key = .init() - CCryptoBoringSSL_MLDSA${parameter_set}_public_from_private(&self.key, &privateKeyBacking.key) - } - - /// Initialize a ML-DSA-${parameter_set} public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - init(rawRepresentation: some DataProtocol) throws { - guard rawRepresentation.count == MLDSA${parameter_set}.PublicKey.Backing.byteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - - let bytes: ContiguousBytes = - rawRepresentation.regions.count == 1 - ? rawRepresentation.regions.first! - : Array(rawRepresentation) - try bytes.withUnsafeBytes { rawBuffer in - try rawBuffer.withMemoryRebound(to: UInt8.self) { buffer in - var cbs = CBS(data: buffer.baseAddress, len: buffer.count) - guard CCryptoBoringSSL_MLDSA${parameter_set}_parse_public_key(&self.key, &cbs) == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - } - } - } - - /// The raw binary representation of the public key. - var rawRepresentation: Data { - var cbb = CBB() - // The following BoringSSL functions can only fail on allocation failure, which we define as impossible. - CCryptoBoringSSL_CBB_init(&cbb, MLDSA${parameter_set}.PublicKey.Backing.byteCount) - defer { CCryptoBoringSSL_CBB_cleanup(&cbb) } - CCryptoBoringSSL_MLDSA${parameter_set}_marshal_public_key(&cbb, &self.key) - return Data(bytes: CCryptoBoringSSL_CBB_data(&cbb), count: CCryptoBoringSSL_CBB_len(&cbb)) - } - - /// Verify a signature for the given data. - /// - /// - Parameters: - /// - signature: The signature to verify. - /// - data: The message to verify the signature against. - /// - context: The context to use for the signature verification. - /// - /// - Returns: `true` if the signature is valid, `false` otherwise. - func isValidSignature( - _ signature: S, - for data: D, - context: C? - ) -> Bool { - let signatureBytes: ContiguousBytes = - signature.regions.count == 1 ? signature.regions.first! : Array(signature) - return signatureBytes.withUnsafeBytes { signaturePtr in - let dataBytes: ContiguousBytes = data.regions.count == 1 ? data.regions.first! : Array(data) - let rc: CInt = dataBytes.withUnsafeBytes { dataPtr in - context.withUnsafeBytes { contextPtr in - CCryptoBoringSSL_MLDSA${parameter_set}_verify( - &self.key, - signaturePtr.baseAddress, - signaturePtr.count, - dataPtr.baseAddress, - dataPtr.count, - contextPtr.baseAddress, - contextPtr.count - ) - } - } - return rc == 1 - } - } - - /// The size of the public key in bytes. - static let byteCount = Int(MLDSA${parameter_set}_PUBLIC_KEY_BYTES) - } - } -} - -@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) -extension MLDSA${parameter_set} { - /// The size of the signature in bytes. - private static let signatureByteCount = Int(MLDSA${parameter_set}_SIGNATURE_BYTES) -} -% end - -private enum MLDSA { - /// The size of the seed in bytes. - fileprivate static let seedByteCount = 32 -} diff --git a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift b/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift deleted file mode 100644 index 70a31b8d4..000000000 --- a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift +++ /dev/null @@ -1,571 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -// MARK: - Generated file, do NOT edit -// any edits of this file WILL be overwritten and thus discarded -// see section `gyb` in `README` for details. - -@_implementationOnly import CCryptoBoringSSL -import Crypto -import Foundation - -/// A module-lattice-based key encapsulation mechanism that provides security against quantum computing attacks. -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -public enum MLKEM768 {} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM768 { - /// A ML-KEM-768 private key. - public struct PrivateKey: Sendable, KEMPrivateKey { - private var backing: Backing - - /// Initialize a ML-KEM-768 private key from a random seed. - public init() { - self.backing = Backing() - } - - /// Generate a ML-KEM-768 private key from a random seed. - /// - /// - Returns: The generated private key. - public static func generate() -> MLKEM768.PrivateKey { - .init() - } - - /// Initialize a ML-KEM-768 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. - public init(seedRepresentation: some DataProtocol) throws { - self.backing = try Backing(seedRepresentation: seedRepresentation) - } - - /// The seed from which this private key was generated. - public var seedRepresentation: Data { - self.backing.seed - } - - /// The public key associated with this private key. - public var publicKey: PublicKey { - self.backing.publicKey - } - - /// Decapsulate a shared secret and create a symmetric key. - /// - /// - Parameter encapsulated: The encapsulated shared secret. - /// - /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. - /// - /// - Returns: The symmetric key. - public func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { - try self.backing.decapsulate(encapsulated) - } - - fileprivate final class Backing { - var key: MLKEM768_private_key - var seed: Data - - /// Initialize a ML-KEM-768 private key from a random seed. - init() { - self.key = .init() - self.seed = Data() - - self.seed = withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM.seedByteCount - ) { seedPtr in - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM768.PublicKey.byteCount - ) { publicKeyPtr in - CCryptoBoringSSL_MLKEM768_generate_key( - publicKeyPtr.baseAddress, - seedPtr.baseAddress, - &self.key - ) - - return Data(bytes: seedPtr.baseAddress!, count: MLKEM.seedByteCount) - } - } - } - - /// Initialize a ML-KEM-768 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. - init(seedRepresentation: some DataProtocol) throws { - guard seedRepresentation.count == MLKEM.seedByteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - self.seed = Data(seedRepresentation) - - guard - self.seed.withUnsafeBytes({ seedPtr in - CCryptoBoringSSL_MLKEM768_private_key_from_seed( - &self.key, - seedPtr.baseAddress, - seedPtr.count - ) - }) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - } - - /// The public key associated with this private key. - var publicKey: PublicKey { - PublicKey(privateKeyBacking: self) - } - - /// Decapsulate a shared secret and create a symmetric key. - /// - /// - Parameter encapsulated: The encapsulated shared secret. - /// - /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. - /// - /// - Returns: The symmetric key. - func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { - guard encapsulated.count == MLKEM768.ciphertextByteCount else { - throw CryptoKitError.incorrectParameterSize - } - - var symmetricKeyData = Data(repeating: 0, count: MLKEM.sharedSecretByteCount) - - let rc: CInt = symmetricKeyData.withUnsafeMutableBytes { symmetricKeyDataPtr in - let bytes: ContiguousBytes = - encapsulated.regions.count == 1 - ? encapsulated.regions.first! - : Array(encapsulated) - return bytes.withUnsafeBytes { encapsulatedPtr in - CCryptoBoringSSL_MLKEM768_decap( - symmetricKeyDataPtr.baseAddress, - encapsulatedPtr.baseAddress, - encapsulatedPtr.count, - &self.key - ) - } - } - - guard rc == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - - return SymmetricKey(data: symmetricKeyData) - } - } - } -} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM768 { - /// A ML-KEM-768 public key. - public struct PublicKey: Sendable, KEMPublicKey { - private var backing: Backing - - fileprivate init(privateKeyBacking: PrivateKey.Backing) { - self.backing = Backing(privateKeyBacking: privateKeyBacking) - } - - /// Initialize a ML-KEM-768 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - public init(rawRepresentation: some DataProtocol) throws { - self.backing = try Backing(rawRepresentation: rawRepresentation) - } - - /// The raw binary representation of the public key. - public var rawRepresentation: Data { - self.backing.rawRepresentation - } - - /// Encapsulate a shared secret. - /// - /// - Returns: The shared secret and its encapsulated version. - public func encapsulate() -> KEM.EncapsulationResult { - self.backing.encapsulate() - } - - /// The size of the public key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - var key: MLKEM768_public_key - - init(privateKeyBacking: PrivateKey.Backing) { - self.key = .init() - CCryptoBoringSSL_MLKEM768_public_from_private(&self.key, &privateKeyBacking.key) - } - - /// Initialize a ML-KEM-768 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - init(rawRepresentation: some DataProtocol) throws { - guard rawRepresentation.count == MLKEM768.PublicKey.byteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - - let bytes: ContiguousBytes = - rawRepresentation.regions.count == 1 - ? rawRepresentation.regions.first! - : Array(rawRepresentation) - try bytes.withUnsafeBytes { rawBuffer in - try rawBuffer.withMemoryRebound(to: UInt8.self) { buffer in - var cbs = CBS(data: buffer.baseAddress, len: buffer.count) - guard CCryptoBoringSSL_MLKEM768_parse_public_key(&self.key, &cbs) == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - } - } - } - - /// The raw binary representation of the public key. - var rawRepresentation: Data { - var cbb = CBB() - // The following BoringSSL functions can only fail on allocation failure, which we define as impossible. - CCryptoBoringSSL_CBB_init(&cbb, MLKEM768.PublicKey.Backing.byteCount) - defer { CCryptoBoringSSL_CBB_cleanup(&cbb) } - CCryptoBoringSSL_MLKEM768_marshal_public_key(&cbb, &self.key) - return Data(bytes: CCryptoBoringSSL_CBB_data(&cbb), count: CCryptoBoringSSL_CBB_len(&cbb)) - } - - /// Encapsulate a shared secret. - /// - /// - Returns: The shared secret and its encapsulated version. - func encapsulate() -> KEM.EncapsulationResult { - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM768.ciphertextByteCount - ) { encapsulatedPtr in - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM.sharedSecretByteCount - ) { secretPtr in - CCryptoBoringSSL_MLKEM768_encap( - encapsulatedPtr.baseAddress, - secretPtr.baseAddress, - &self.key - ) - - return KEM.EncapsulationResult( - sharedSecret: SymmetricKey( - data: Data(bytes: secretPtr.baseAddress!, count: MLKEM.sharedSecretByteCount) - ), - encapsulated: Data( - bytes: encapsulatedPtr.baseAddress!, - count: MLKEM768.ciphertextByteCount - ) - ) - } - } - } - - /// The size of the public key in bytes. - static let byteCount = Int(MLKEM768_PUBLIC_KEY_BYTES) - } - } -} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM768 { - /// The size of the encapsulated shared secret in bytes. - private static let ciphertextByteCount = Int(MLKEM768_CIPHERTEXT_BYTES) -} - -/// A module-lattice-based key encapsulation mechanism that provides security against quantum computing attacks. -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -public enum MLKEM1024 {} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM1024 { - /// A ML-KEM-1024 private key. - public struct PrivateKey: Sendable, KEMPrivateKey { - private var backing: Backing - - /// Initialize a ML-KEM-1024 private key from a random seed. - public init() { - self.backing = Backing() - } - - /// Generate a ML-KEM-1024 private key from a random seed. - /// - /// - Returns: The generated private key. - public static func generate() -> MLKEM1024.PrivateKey { - .init() - } - - /// Initialize a ML-KEM-1024 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. - public init(seedRepresentation: some DataProtocol) throws { - self.backing = try Backing(seedRepresentation: seedRepresentation) - } - - /// The seed from which this private key was generated. - public var seedRepresentation: Data { - self.backing.seed - } - - /// The public key associated with this private key. - public var publicKey: PublicKey { - self.backing.publicKey - } - - /// Decapsulate a shared secret and create a symmetric key. - /// - /// - Parameter encapsulated: The encapsulated shared secret. - /// - /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. - /// - /// - Returns: The symmetric key. - public func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { - try self.backing.decapsulate(encapsulated) - } - - fileprivate final class Backing { - var key: MLKEM1024_private_key - var seed: Data - - /// Initialize a ML-KEM-1024 private key from a random seed. - init() { - self.key = .init() - self.seed = Data() - - self.seed = withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM.seedByteCount - ) { seedPtr in - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM1024.PublicKey.byteCount - ) { publicKeyPtr in - CCryptoBoringSSL_MLKEM1024_generate_key( - publicKeyPtr.baseAddress, - seedPtr.baseAddress, - &self.key - ) - - return Data(bytes: seedPtr.baseAddress!, count: MLKEM.seedByteCount) - } - } - } - - /// Initialize a ML-KEM-1024 private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. - init(seedRepresentation: some DataProtocol) throws { - guard seedRepresentation.count == MLKEM.seedByteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - self.seed = Data(seedRepresentation) - - guard - self.seed.withUnsafeBytes({ seedPtr in - CCryptoBoringSSL_MLKEM1024_private_key_from_seed( - &self.key, - seedPtr.baseAddress, - seedPtr.count - ) - }) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - } - - /// The public key associated with this private key. - var publicKey: PublicKey { - PublicKey(privateKeyBacking: self) - } - - /// Decapsulate a shared secret and create a symmetric key. - /// - /// - Parameter encapsulated: The encapsulated shared secret. - /// - /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. - /// - /// - Returns: The symmetric key. - func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { - guard encapsulated.count == MLKEM1024.ciphertextByteCount else { - throw CryptoKitError.incorrectParameterSize - } - - var symmetricKeyData = Data(repeating: 0, count: MLKEM.sharedSecretByteCount) - - let rc: CInt = symmetricKeyData.withUnsafeMutableBytes { symmetricKeyDataPtr in - let bytes: ContiguousBytes = - encapsulated.regions.count == 1 - ? encapsulated.regions.first! - : Array(encapsulated) - return bytes.withUnsafeBytes { encapsulatedPtr in - CCryptoBoringSSL_MLKEM1024_decap( - symmetricKeyDataPtr.baseAddress, - encapsulatedPtr.baseAddress, - encapsulatedPtr.count, - &self.key - ) - } - } - - guard rc == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - - return SymmetricKey(data: symmetricKeyData) - } - } - } -} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM1024 { - /// A ML-KEM-1024 public key. - public struct PublicKey: Sendable, KEMPublicKey { - private var backing: Backing - - fileprivate init(privateKeyBacking: PrivateKey.Backing) { - self.backing = Backing(privateKeyBacking: privateKeyBacking) - } - - /// Initialize a ML-KEM-1024 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - public init(rawRepresentation: some DataProtocol) throws { - self.backing = try Backing(rawRepresentation: rawRepresentation) - } - - /// The raw binary representation of the public key. - public var rawRepresentation: Data { - self.backing.rawRepresentation - } - - /// Encapsulate a shared secret. - /// - /// - Returns: The shared secret and its encapsulated version. - public func encapsulate() -> KEM.EncapsulationResult { - self.backing.encapsulate() - } - - /// The size of the public key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - var key: MLKEM1024_public_key - - init(privateKeyBacking: PrivateKey.Backing) { - self.key = .init() - CCryptoBoringSSL_MLKEM1024_public_from_private(&self.key, &privateKeyBacking.key) - } - - /// Initialize a ML-KEM-1024 public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - init(rawRepresentation: some DataProtocol) throws { - guard rawRepresentation.count == MLKEM1024.PublicKey.byteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - - let bytes: ContiguousBytes = - rawRepresentation.regions.count == 1 - ? rawRepresentation.regions.first! - : Array(rawRepresentation) - try bytes.withUnsafeBytes { rawBuffer in - try rawBuffer.withMemoryRebound(to: UInt8.self) { buffer in - var cbs = CBS(data: buffer.baseAddress, len: buffer.count) - guard CCryptoBoringSSL_MLKEM1024_parse_public_key(&self.key, &cbs) == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - } - } - } - - /// The raw binary representation of the public key. - var rawRepresentation: Data { - var cbb = CBB() - // The following BoringSSL functions can only fail on allocation failure, which we define as impossible. - CCryptoBoringSSL_CBB_init(&cbb, MLKEM1024.PublicKey.Backing.byteCount) - defer { CCryptoBoringSSL_CBB_cleanup(&cbb) } - CCryptoBoringSSL_MLKEM1024_marshal_public_key(&cbb, &self.key) - return Data(bytes: CCryptoBoringSSL_CBB_data(&cbb), count: CCryptoBoringSSL_CBB_len(&cbb)) - } - - /// Encapsulate a shared secret. - /// - /// - Returns: The shared secret and its encapsulated version. - func encapsulate() -> KEM.EncapsulationResult { - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM1024.ciphertextByteCount - ) { encapsulatedPtr in - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM.sharedSecretByteCount - ) { secretPtr in - CCryptoBoringSSL_MLKEM1024_encap( - encapsulatedPtr.baseAddress, - secretPtr.baseAddress, - &self.key - ) - - return KEM.EncapsulationResult( - sharedSecret: SymmetricKey( - data: Data(bytes: secretPtr.baseAddress!, count: MLKEM.sharedSecretByteCount) - ), - encapsulated: Data( - bytes: encapsulatedPtr.baseAddress!, - count: MLKEM1024.ciphertextByteCount - ) - ) - } - } - } - - /// The size of the public key in bytes. - static let byteCount = Int(MLKEM1024_PUBLIC_KEY_BYTES) - } - } -} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM1024 { - /// The size of the encapsulated shared secret in bytes. - private static let ciphertextByteCount = Int(MLKEM1024_CIPHERTEXT_BYTES) -} - -private enum MLKEM { - /// The size of the seed in bytes. - fileprivate static let seedByteCount = 64 - - // The size of the shared secret in bytes. - fileprivate static let sharedSecretByteCount = 32 -} diff --git a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb b/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb deleted file mode 100644 index 8b1ae5971..000000000 --- a/Sources/_CryptoExtras/MLKEM/MLKEM_boring.swift.gyb +++ /dev/null @@ -1,305 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -// MARK: - Generated file, do NOT edit -// any edits of this file WILL be overwritten and thus discarded -// see section `gyb` in `README` for details. - -@_implementationOnly import CCryptoBoringSSL -import Crypto -import Foundation -%{ - parameter_sets = ["768", "1024"] -}% -% for parameter_set in parameter_sets: - -/// A module-lattice-based key encapsulation mechanism that provides security against quantum computing attacks. -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -public enum MLKEM${parameter_set} {} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM${parameter_set} { - /// A ML-KEM-${parameter_set} private key. - public struct PrivateKey: Sendable, KEMPrivateKey { - private var backing: Backing - - /// Initialize a ML-KEM-${parameter_set} private key from a random seed. - public init() { - self.backing = Backing() - } - - /// Generate a ML-KEM-${parameter_set} private key from a random seed. - /// - /// - Returns: The generated private key. - public static func generate() -> MLKEM${parameter_set}.PrivateKey { - .init() - } - - /// Initialize a ML-KEM-${parameter_set} private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. - public init(seedRepresentation: some DataProtocol) throws { - self.backing = try Backing(seedRepresentation: seedRepresentation) - } - - /// The seed from which this private key was generated. - public var seedRepresentation: Data { - self.backing.seed - } - - /// The public key associated with this private key. - public var publicKey: PublicKey { - self.backing.publicKey - } - - /// Decapsulate a shared secret and create a symmetric key. - /// - /// - Parameter encapsulated: The encapsulated shared secret. - /// - /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. - /// - /// - Returns: The symmetric key. - public func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { - try self.backing.decapsulate(encapsulated) - } - - fileprivate final class Backing { - var key: MLKEM${parameter_set}_private_key - var seed: Data - - /// Initialize a ML-KEM-${parameter_set} private key from a random seed. - init() { - self.key = .init() - self.seed = Data() - - self.seed = withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM.seedByteCount - ) { seedPtr in - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM${parameter_set}.PublicKey.byteCount - ) { publicKeyPtr in - CCryptoBoringSSL_MLKEM${parameter_set}_generate_key( - publicKeyPtr.baseAddress, - seedPtr.baseAddress, - &self.key - ) - - return Data(bytes: seedPtr.baseAddress!, count: MLKEM.seedByteCount) - } - } - } - - /// Initialize a ML-KEM-${parameter_set} private key from a seed. - /// - /// - Parameter seedRepresentation: The seed to use to generate the private key. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the seed is not 64 bytes long. - init(seedRepresentation: some DataProtocol) throws { - guard seedRepresentation.count == MLKEM.seedByteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - self.seed = Data(seedRepresentation) - - guard - self.seed.withUnsafeBytes({ seedPtr in - CCryptoBoringSSL_MLKEM${parameter_set}_private_key_from_seed( - &self.key, - seedPtr.baseAddress, - seedPtr.count - ) - }) == 1 - else { - throw CryptoKitError.internalBoringSSLError() - } - } - - /// The public key associated with this private key. - var publicKey: PublicKey { - PublicKey(privateKeyBacking: self) - } - - /// Decapsulate a shared secret and create a symmetric key. - /// - /// - Parameter encapsulated: The encapsulated shared secret. - /// - /// - Throws: `CryptoError.incorrectParameterSize` if the encapsulated shared secret is not 1088 bytes long. - /// - /// - Returns: The symmetric key. - func decapsulate(_ encapsulated: some DataProtocol) throws -> SymmetricKey { - guard encapsulated.count == MLKEM${parameter_set}.ciphertextByteCount else { - throw CryptoKitError.incorrectParameterSize - } - - var symmetricKeyData = Data(repeating: 0, count: MLKEM.sharedSecretByteCount) - - let rc: CInt = symmetricKeyData.withUnsafeMutableBytes { symmetricKeyDataPtr in - let bytes: ContiguousBytes = - encapsulated.regions.count == 1 - ? encapsulated.regions.first! - : Array(encapsulated) - return bytes.withUnsafeBytes { encapsulatedPtr in - CCryptoBoringSSL_MLKEM${parameter_set}_decap( - symmetricKeyDataPtr.baseAddress, - encapsulatedPtr.baseAddress, - encapsulatedPtr.count, - &self.key - ) - } - } - - guard rc == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - - return SymmetricKey(data: symmetricKeyData) - } - } - } -} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM${parameter_set} { - /// A ML-KEM-${parameter_set} public key. - public struct PublicKey: Sendable, KEMPublicKey { - private var backing: Backing - - fileprivate init(privateKeyBacking: PrivateKey.Backing) { - self.backing = Backing(privateKeyBacking: privateKeyBacking) - } - - /// Initialize a ML-KEM-${parameter_set} public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - public init(rawRepresentation: some DataProtocol) throws { - self.backing = try Backing(rawRepresentation: rawRepresentation) - } - - /// The raw binary representation of the public key. - public var rawRepresentation: Data { - self.backing.rawRepresentation - } - - /// Encapsulate a shared secret. - /// - /// - Returns: The shared secret and its encapsulated version. - public func encapsulate() -> KEM.EncapsulationResult { - self.backing.encapsulate() - } - - /// The size of the public key in bytes. - static let byteCount = Backing.byteCount - - fileprivate final class Backing { - var key: MLKEM${parameter_set}_public_key - - init(privateKeyBacking: PrivateKey.Backing) { - self.key = .init() - CCryptoBoringSSL_MLKEM${parameter_set}_public_from_private(&self.key, &privateKeyBacking.key) - } - - /// Initialize a ML-KEM-${parameter_set} public key from a raw representation. - /// - /// - Parameter rawRepresentation: The public key bytes. - /// - /// - Throws: `CryptoError.incorrectKeySize` if the raw representation is not the correct size. - init(rawRepresentation: some DataProtocol) throws { - guard rawRepresentation.count == MLKEM${parameter_set}.PublicKey.byteCount else { - throw CryptoKitError.incorrectKeySize - } - - self.key = .init() - - let bytes: ContiguousBytes = - rawRepresentation.regions.count == 1 - ? rawRepresentation.regions.first! - : Array(rawRepresentation) - try bytes.withUnsafeBytes { rawBuffer in - try rawBuffer.withMemoryRebound(to: UInt8.self) { buffer in - var cbs = CBS(data: buffer.baseAddress, len: buffer.count) - guard CCryptoBoringSSL_MLKEM${parameter_set}_parse_public_key(&self.key, &cbs) == 1 else { - throw CryptoKitError.internalBoringSSLError() - } - } - } - } - - /// The raw binary representation of the public key. - var rawRepresentation: Data { - var cbb = CBB() - // The following BoringSSL functions can only fail on allocation failure, which we define as impossible. - CCryptoBoringSSL_CBB_init(&cbb, MLKEM${parameter_set}.PublicKey.Backing.byteCount) - defer { CCryptoBoringSSL_CBB_cleanup(&cbb) } - CCryptoBoringSSL_MLKEM${parameter_set}_marshal_public_key(&cbb, &self.key) - return Data(bytes: CCryptoBoringSSL_CBB_data(&cbb), count: CCryptoBoringSSL_CBB_len(&cbb)) - } - - /// Encapsulate a shared secret. - /// - /// - Returns: The shared secret and its encapsulated version. - func encapsulate() -> KEM.EncapsulationResult { - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM${parameter_set}.ciphertextByteCount - ) { encapsulatedPtr in - withUnsafeTemporaryAllocation( - of: UInt8.self, - capacity: MLKEM.sharedSecretByteCount - ) { secretPtr in - CCryptoBoringSSL_MLKEM${parameter_set}_encap( - encapsulatedPtr.baseAddress, - secretPtr.baseAddress, - &self.key - ) - - return KEM.EncapsulationResult( - sharedSecret: SymmetricKey( - data: Data(bytes: secretPtr.baseAddress!, count: MLKEM.sharedSecretByteCount) - ), - encapsulated: Data( - bytes: encapsulatedPtr.baseAddress!, - count: MLKEM${parameter_set}.ciphertextByteCount - ) - ) - } - } - } - - /// The size of the public key in bytes. - static let byteCount = Int(MLKEM${parameter_set}_PUBLIC_KEY_BYTES) - } - } -} - -@available(macOS 14.0, iOS 17, watchOS 10, tvOS 17, macCatalyst 17, visionOS 1.0, *) -extension MLKEM${parameter_set} { - /// The size of the encapsulated shared secret in bytes. - private static let ciphertextByteCount = Int(MLKEM${parameter_set}_CIPHERTEXT_BYTES) -} -% end - -private enum MLKEM { - /// The size of the seed in bytes. - fileprivate static let seedByteCount = 64 - - // The size of the shared secret in bytes. - fileprivate static let sharedSecretByteCount = 32 -} diff --git a/Sources/_CryptoExtras/Util/Optional+withUnsafeBytes.swift b/Sources/_CryptoExtras/Util/Optional+withUnsafeBytes.swift deleted file mode 100644 index 6f9a2a251..000000000 --- a/Sources/_CryptoExtras/Util/Optional+withUnsafeBytes.swift +++ /dev/null @@ -1,26 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation - -extension Optional where Wrapped: DataProtocol { - func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> ReturnValue) rethrows -> ReturnValue { - if let self { - let bytes: ContiguousBytes = self.regions.count == 1 ? self.regions.first! : Array(self) - return try bytes.withUnsafeBytes { try body($0) } - } else { - return try body(UnsafeRawBufferPointer(start: nil, count: 0)) - } - } -} diff --git a/Tests/_CryptoExtrasTests/MLDSATests.swift b/Tests/_CryptoExtrasTests/MLDSATests.swift deleted file mode 100644 index e19582dc5..000000000 --- a/Tests/_CryptoExtrasTests/MLDSATests.swift +++ /dev/null @@ -1,305 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import XCTest - -@testable import _CryptoExtras - -final class MLDSATests: XCTestCase { - func testMLDSA65Signing() throws { - try testMLDSA65Signing(MLDSA65.PrivateKey()) - let seed: [UInt8] = (0..<32).map { _ in UInt8.random(in: 0...255) } - try testMLDSA65Signing(MLDSA65.PrivateKey(seedRepresentation: seed)) - } - - private func testMLDSA65Signing(_ key: MLDSA65.PrivateKey) throws { - let test = "Hello, world!".data(using: .utf8)! - try XCTAssertTrue( - key.publicKey.isValidSignature( - key.signature(for: test), - for: test - ) - ) - - let context = "ctx".data(using: .utf8)! - try XCTAssertTrue( - key.publicKey.isValidSignature( - key.signature(for: test, context: context), - for: test, - context: context - ) - ) - } - - func testMLDSA87Signing() throws { - try testMLDSA87Signing(MLDSA87.PrivateKey()) - let seed: [UInt8] = (0..<32).map { _ in UInt8.random(in: 0...255) } - try testMLDSA87Signing(MLDSA87.PrivateKey(seedRepresentation: seed)) - } - - private func testMLDSA87Signing(_ key: MLDSA87.PrivateKey) throws { - let test = "Hello, world!".data(using: .utf8)! - try XCTAssertTrue( - key.publicKey.isValidSignature( - key.signature(for: test), - for: test - ) - ) - - let context = "ctx".data(using: .utf8)! - try XCTAssertTrue( - key.publicKey.isValidSignature( - key.signature(for: test, context: context), - for: test, - context: context - ) - ) - } - - func testMLDSA65SeedRoundTripping() throws { - let key = try MLDSA65.PrivateKey() - let seed = key.seedRepresentation - let roundTripped = try MLDSA65.PrivateKey(seedRepresentation: seed) - XCTAssertEqual(seed, roundTripped.seedRepresentation) - XCTAssertEqual(key.publicKey.rawRepresentation, roundTripped.publicKey.rawRepresentation) - } - - func testMLDSA87SeedRoundTripping() throws { - let key = try MLDSA87.PrivateKey() - let seed = key.seedRepresentation - let roundTripped = try MLDSA87.PrivateKey(seedRepresentation: seed) - XCTAssertEqual(seed, roundTripped.seedRepresentation) - XCTAssertEqual(key.publicKey.rawRepresentation, roundTripped.publicKey.rawRepresentation) - } - - func testMLDSA65SignatureIsRandomized() throws { - let message = "Hello, world!".data(using: .utf8)! - - let seed: [UInt8] = (0..<32).map { _ in UInt8.random(in: 0...255) } - let key = try MLDSA65.PrivateKey(seedRepresentation: seed) - let publicKey = key.publicKey - - let signature1 = try key.signature(for: message) - let signature2 = try key.signature(for: message) - - XCTAssertNotEqual(signature1, signature2) - - // Even though the signatures are different, they both verify. - XCTAssertTrue(publicKey.isValidSignature(signature1, for: message)) - XCTAssertTrue(publicKey.isValidSignature(signature2, for: message)) - } - - func testMLDSA87SignatureIsRandomized() throws { - let message = "Hello, world!".data(using: .utf8)! - - let seed: [UInt8] = (0..<32).map { _ in UInt8.random(in: 0...255) } - let key = try MLDSA87.PrivateKey(seedRepresentation: seed) - let publicKey = key.publicKey - - let signature1 = try key.signature(for: message) - let signature2 = try key.signature(for: message) - - XCTAssertNotEqual(signature1, signature2) - - // Even though the signatures are different, they both verify. - XCTAssertTrue(publicKey.isValidSignature(signature1, for: message)) - XCTAssertTrue(publicKey.isValidSignature(signature2, for: message)) - } - - func testInvalidMLDSA65PublicKeyEncodingLength() throws { - // Encode a public key with a trailing 0 at the end. - var encodedPublicKey = [UInt8](repeating: 0, count: MLDSA65.PublicKey.byteCount + 1) - let seed: [UInt8] = (0..<32).map { _ in UInt8.random(in: 0...255) } - let key = try MLDSA65.PrivateKey(seedRepresentation: seed) - let publicKey = key.publicKey - encodedPublicKey.replaceSubrange(0..: Decodable { - let testVectors: [Vector] - } - - private func nistTest( - jsonName: String, - file: StaticString = #file, - line: UInt = #line, - testFunction: (Vector) throws -> Void - ) throws { - var fileURL = URL(fileURLWithPath: "\(#file)") - for _ in 0..<2 { - fileURL.deleteLastPathComponent() - } - fileURL = fileURL.appendingPathComponent("_CryptoExtrasVectors", isDirectory: true) - fileURL = fileURL.appendingPathComponent("\(jsonName).json", isDirectory: false) - - let data = try Data(contentsOf: fileURL) - - let testFile = try JSONDecoder().decode(NISTTestFile.self, from: data) - - for vector in testFile.testVectors { - try testFunction(vector) - } - } - - func testMLDSA65WycheproofVerifyFile() throws { - try wycheproofTest(jsonName: "mldsa_65_verify_test") { (testGroup: WycheproofTestGroup) in - let publicKey: MLDSA65.PublicKey - do { - publicKey = try MLDSA65.PublicKey(rawRepresentation: Data(hexString: testGroup.publicKey)) - } catch { - if testGroup.tests.contains(where: { $0.flags.contains(.incorrectPublicKeyLength) }) { return } - throw error - } - for test in testGroup.tests { - let message = try Data(hexString: test.msg) - let signature = try Data(hexString: test.sig) - let context = try test.ctx.map { try Data(hexString: $0) } - - switch test.result { - case .valid: - if let context { - XCTAssertTrue(publicKey.isValidSignature(signature, for: message, context: context)) - } else { - XCTAssertTrue(publicKey.isValidSignature(signature, for: message)) - } - case .invalid: - if let context { - XCTAssertFalse(publicKey.isValidSignature(signature, for: message, context: context)) - } else { - XCTAssertFalse(publicKey.isValidSignature(signature, for: message)) - } - } - } - } - } - - func testMLDSA87WycheproofVerifyFile() throws { - try wycheproofTest(jsonName: "mldsa_87_verify_test") { (testGroup: WycheproofTestGroup) in - let publicKey: MLDSA87.PublicKey - do { - publicKey = try MLDSA87.PublicKey(rawRepresentation: Data(hexString: testGroup.publicKey)) - } catch { - if testGroup.tests.contains(where: { $0.flags.contains(.incorrectPublicKeyLength) }) { return } - throw error - } - for test in testGroup.tests { - let message = try Data(hexString: test.msg) - let signature = try Data(hexString: test.sig) - let context = try test.ctx.map { try Data(hexString: $0) } - - switch test.result { - case .valid: - if let context { - XCTAssertTrue(publicKey.isValidSignature(signature, for: message, context: context)) - } else { - XCTAssertTrue(publicKey.isValidSignature(signature, for: message)) - } - case .invalid: - if let context { - XCTAssertFalse(publicKey.isValidSignature(signature, for: message, context: context)) - } else { - XCTAssertFalse(publicKey.isValidSignature(signature, for: message)) - } - } - } - } - } - - struct WycheproofTestGroup: Codable { - let publicKey: String - let tests: [WycheproofTest] - - struct WycheproofTest: Codable { - let msg, sig: String - let result: Result - let flags: [Flag] - let ctx: String? - - enum Flag: String, Codable { - case boundaryCondition = "BoundaryCondition" - case incorrectPublicKeyLength = "IncorrectPublicKeyLength" - case incorrectSignatureLength = "IncorrectSignatureLength" - case invalidContext = "InvalidContext" - case invalidHintsEncoding = "InvalidHintsEncoding" - case invalidPrivateKey = "InvalidPrivateKey" - case manySteps = "ManySteps" - case modifiedSignature = "ModifiedSignature" - case validSignature = "ValidSignature" - case zeroPublicKey = "ZeroPublicKey" - } - - enum Result: String, Codable { - case invalid - case valid - } - } - } -} diff --git a/Tests/_CryptoExtrasTests/MLKEMTests.swift b/Tests/_CryptoExtrasTests/MLKEMTests.swift deleted file mode 100644 index 8a0cb8892..000000000 --- a/Tests/_CryptoExtrasTests/MLKEMTests.swift +++ /dev/null @@ -1,107 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Crypto -import XCTest - -@testable import _CryptoExtras - -@available(macOS 14.0, *) -final class MLKEMTests: XCTestCase { - func testMLKEM768() throws { - // Generate a key pair - let privateKey = MLKEM768.PrivateKey() - let publicKey = privateKey.publicKey - - // Serialize and deserialize the private key - let seed = privateKey.seedRepresentation - let privateKey2 = try MLKEM768.PrivateKey(seedRepresentation: seed) - XCTAssertEqual(privateKey.seedRepresentation, privateKey2.seedRepresentation) - - // Serialize and deserialize the public key - let publicKeyBytes = publicKey.rawRepresentation - var modifiedPublicKeyBytes = publicKeyBytes - modifiedPublicKeyBytes[0] = 0xff - modifiedPublicKeyBytes[1] = 0xff - // Parsing should fail because the first coefficient is >= kPrime; - XCTAssertThrowsError(try MLKEM768.PublicKey(rawRepresentation: modifiedPublicKeyBytes)) - - let publicKey2 = try MLKEM768.PublicKey(rawRepresentation: publicKeyBytes) - XCTAssertEqual(publicKeyBytes, publicKey2.rawRepresentation) - - // Ensure public key derived from private key matches the original public key - let derivedPublicKey = privateKey.publicKey - XCTAssertEqual(publicKeyBytes, derivedPublicKey.rawRepresentation) - - // Serialize and deserialize the private key with modifications - var modifiedSeed = privateKey.seedRepresentation - modifiedSeed[0] = 0xff - modifiedSeed[1] = 0xff - XCTAssertNotEqual( - try MLKEM768.PrivateKey(seedRepresentation: modifiedSeed).publicKey.rawRepresentation, - publicKeyBytes - ) - - // Encapsulation and decapsulation - let encapsulationResult = publicKey.encapsulate() - let sharedSecret1 = encapsulationResult.sharedSecret - let ciphertext = encapsulationResult.encapsulated - - let sharedSecret2 = try privateKey.decapsulate(ciphertext) - XCTAssertEqual(sharedSecret1, sharedSecret2) - } - - func testMLKEM1024() throws { - // Generate a key pair - let privateKey = MLKEM1024.PrivateKey() - let publicKey = privateKey.publicKey - - // Serialize and deserialize the private key - let seed = privateKey.seedRepresentation - let privateKey2 = try MLKEM1024.PrivateKey(seedRepresentation: seed) - XCTAssertEqual(privateKey.seedRepresentation, privateKey2.seedRepresentation) - - // Serialize and deserialize the public key - let publicKeyBytes = publicKey.rawRepresentation - var modifiedPublicKeyBytes = publicKeyBytes - modifiedPublicKeyBytes[0] = 0xff - modifiedPublicKeyBytes[1] = 0xff - // Parsing should fail because the first coefficient is >= kPrime; - XCTAssertThrowsError(try MLKEM1024.PublicKey(rawRepresentation: modifiedPublicKeyBytes)) - - let publicKey2 = try MLKEM1024.PublicKey(rawRepresentation: publicKeyBytes) - XCTAssertEqual(publicKeyBytes, publicKey2.rawRepresentation) - - // Ensure public key derived from private key matches the original public key - let derivedPublicKey = privateKey.publicKey - XCTAssertEqual(publicKeyBytes, derivedPublicKey.rawRepresentation) - - // Serialize and deserialize the private key with modifications - var modifiedSeed = privateKey.seedRepresentation - modifiedSeed[0] = 0xff - modifiedSeed[1] = 0xff - XCTAssertNotEqual( - try MLKEM1024.PrivateKey(seedRepresentation: modifiedSeed).publicKey.rawRepresentation, - publicKeyBytes - ) - - // Encapsulation and decapsulation - let encapsulationResult = publicKey.encapsulate() - let sharedSecret1 = encapsulationResult.sharedSecret - let ciphertext = encapsulationResult.encapsulated - - let sharedSecret2 = try privateKey.decapsulate(ciphertext) - XCTAssertEqual(sharedSecret1, sharedSecret2) - } -} diff --git a/Tests/_CryptoExtrasVectors/mldsa_65_verify_test.json b/Tests/_CryptoExtrasVectors/mldsa_65_verify_test.json deleted file mode 100644 index b7d069711..000000000 --- a/Tests/_CryptoExtrasVectors/mldsa_65_verify_test.json +++ /dev/null @@ -1,1026 +0,0 @@ -{ - "algorithm": "ML-DSA-65", - "generatorVersion": "1", - "header": [ - "Test vectors of type MlDsaVerify are meant for the verification of ML-DSA signatures" - ], - "notes": { - "BoundaryCondition": { - "bugType": "EDGE_CASE", - "description": "This case exercises a boundary condition (e.g. in the signing rejection loop). The verification algorithm may not notice." - }, - "IncorrectPublicKeyLength": { - "bugType": "BASIC", - "description": "The public key has an incorrect length." - }, - "IncorrectSignatureLength": { - "bugType": "BASIC", - "description": "The signature has an incorrect length." - }, - "InvalidContext": { - "bugType": "BASIC", - "description": "The context is invalid (too long)." - }, - "InvalidHintsEncoding": { - "bugType": "BASIC", - "description": "The encoding of hints in the signature is invalid (e.g. non-canonical order)." - }, - "InvalidPrivateKey": { - "bugType": "BASIC", - "description": "The private key is invalid, but the verifier does not know that." - }, - "ManySteps": { - "bugType": "EDGE_CASE", - "description": "This case requires many steps (e.g. many hashes in the matrix expansion, many iterations in the signing rejection loop). The verification algorithm may not notice." - }, - "ModifiedSignature": { - "bugType": "BASIC", - "description": "The test vector contains an invalid signature, generated by modifying a valid signature (e.g. flipping a bit)." - }, - "ValidSignature": { - "bugType": "BASIC", - "description": "The test vector contains a valid signature." - }, - "ZeroPublicKey": { - "bugType": "EDGE_CASE", - "description": "The public key contains a zero vector. This makes it trivial to forge signatures, but that's none of the verification algorithm's business." - } - }, - "numberOfTests": 83, - "schema": "mldsa_verify_schema.json", - "testGroups": [ - { - "type": "MlDsaVerify", - "publicKey": "f5408337d0fee65c28851226a5fa81b58464632c78e2a9bef70d330f2e3a5f74d9cf676aedd1067c91a5dd5d4edc46f868a93ffec9f44e254e44f682a153aeadf228e8db7c5fcfed30cc3408e261ab896876bee56660d2a7c1d7eac20c5754255206a178f7156295065ce7876f90c48f44bc37f3a00e32eefd3a4bb1e298fe283d106eaef92a33a594253a2a0790976a1d04636f8672d28c06c852ea8bb43b84bff512996e7616963d5b9a2906466a152c7ea9be178be35405683b44367af85d2daad87630c1e21ba5490154f0141780f5ed0407cb0b975dd56d5930f9b26413b843b83f3693304b0038bd3e4bb398868060ea18c9c67099376470a50deb052e4056743fbcdf0341b192663bd1c21ba3b3d5666e0d0e29c4e1ed0759ab0bd9d1d355011b94e0ff0c049b03ddb7138640667144fcacd7265f55a07e5387f1abd30c037cf14d436aa855f827049215440d8007f61460500d943f57ffb6bfee6fedd2fcec52882d7d8da1aab29e892c8beac3df3234b4a7d2eca3a45c6623c52bbdd07c1c94314b706988a52029f8f8b06e874b741d72926652c78c6ace2cfd8864eadb2e4b39cafe6e03e4edbafa2747db9bc42f92af8b031e3e380846b1bfd15ade88c285d6a6fffe91eafc8b17de6cbc68575f323cc09fc20e49e8efd76f9568bec486b78df4245428d8d0d5f53873e11de65fda4c770b521a8c67f5c51d48cc26358954514447881fd9a42e5891dac7e1db5249d7861b322111e5fb929bee9ff5e9d5a2667ba93e63fc03040d2e82648f89e89dec1d1d2dfb9efeceb7940f7dcbebeb5a239cc1c54d8f7d52cba220d0634e15df46a58280bc5a48840bd39274cfde150f9ad9a40f6398d715350925f0e0501944409f32331a362bdaaafb3d8ce71c964332d6afb7e684f99951246d88081c86744ae68133f22c53a4b5ae258f230a98491d2d43a79a6d0f4d54a3b62013965ac7c82d0507125a38a0277f81cbc1d46cef2a131c6f51b88ec0baae0c82a6a0e72831cb06f9116cff5111d597e01057d32805a008f52c9aec3311139bfb35982789ff83bdd0c31e9f1080e8ed8eb99fde66bafb29e3357389fe3785b60c78e229ef073e1b65e34d848bd4d8a4f251551e2d38d2546afbc205d3c6dab34d2b962b1afb44f1d22fc10c6744fcd6b636afd3cb414b16c2e0d708fe9f51ff19120bde693b028b6d1e6dbe37b4b8b3bc7c6f7a842701603869d3ded572500f085502efc8d3cc62b30e5cdbcb5e86d9c0d42973bf755df539cc0aea58f9148386db67bd2bf70cd12ccd96d5c66fb271416b772465228dc44b079178f9b766370b66a79b871faca246ca6f8f63be9f0668297ac446cad5cf4a83318b1b00ecbd283f0eecee60a9a37a27abdbdbe382e307970002837dfc0bd3934ebd008918fd4bd383c02c9d37f694996e989a49075767ebc4a2981ef5275455e026cb0bd70946cdd1fadaf251381d324f9efbb860d1b280c29685bab97d010676273b45cca12ac3966aae342c84e2357eccf252577743b8787967b40b07ef2d3d9e6c1a3bcb059cba0fdb7f0d4f815c242b8e14acd3375e608e9230ba3cf8718f43882a3e1e661a2bbe81830d34741f33473e263b3790abe67acf29f5df44865b2ffbc96975fd62738a64112deda5a2534fb0a23b3b3024df986391badf9041c593c313a7ca1e1fcffcb65b07b9a99337b4a4acf616cbe1553eb9541f38aa6247342905995233a28172ca13396b2a9662970120f82b92a213f43de7a232ccca3268265c9ce042d50915430a6c455f32277da42f9962fb9163b623231ebc080fa7b8e9f9021fcf85b98f9c483e4d2226b9326a5bcb2e7449ef029ae142d3a0f0c28bd4f7e9c51a12e1336f24dfacbc3f808a8f7dd683027bc948763b808fb0037394b8b41bc9b2ec7887e67584e03d11b15ca203b2bcb43f8881638c4e4eee7f846d09c7f89b7739df22b2c3acc235032ba8f7ae27b5b9d25733143e80a4cdde6770719c1e66ec2ce683612233e88fafff84c0745a98aa1254c8219c6c556348c2b5d1beeb61532d6bf7bde153271dc647460beb65fe0055b33fd6480dcbb9d7d471952cfa5be260c39721a8c5c89b9e966ae2dc9036451ec9f2c49433b2225e13f23e20c2bfba81a7b3a555883449238f7d48213e9f10ce19e76f1bdcfc73ee5524bd7d8be0a4b46784e238233c04fb99383ec7726f9717e1179dd14fba9ad6c2ebd1699f0ab0e57e6cad23875b029e89cfda06f51266ecd2eed4edafb51e82f2a506d57ba74da611774ca5fa2fff4a976519de425885e7d09219cf815b1767d4fc5a72c18918991a285086a6a766614a4d245387da50f28dd778fb33ab88c0918feba3768c55bb1f07aec33cfeed33d6faa4d34fd7227b365533c1e67dbc89f0b20195cf1cbd480d333ade1c9bb28308085b72ced430268c1492a27050c43668adc9cf8b8509447cfcd3c8f8d8eb554f704101786aa9ebca86991d250776a37a1f56fbf7d08e591f978da49c3870625879f70e2418aec5cba32fa8c346fa9038baebc35ad0068a4d03537aee14c2e71570a87490377fa8dd66f995aa044a522f0c7025a7ab2dd5ad30a64268dc112b7f9fa156df64d631f55f1d6edc55cec570a9c7372e29e02c8d4867bae249431dcf6ed2794a0183f0f7501201feca4a81d334c642fc8d38e9a90fa77429665e09e214797dfa455ff47c4f219d3a2cb0176bc2236455123c1c5da714ad29d580fb194f87173a18dc", - "tests": [ - { - "tcId": 1, - "comment": "baseline", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 2, - "comment": "empty provided context", - "msg": "48656c6c6f20776f726c64", - "ctx": "", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 3, - "comment": "non-empty context", - "msg": "48656c6c6f20776f726c64", - "ctx": "436f6e74657874", - "sig": "3a1f0e89fa72e489e2c4c1607b0f22ad03513725660d1ed7cc9a6b83580247a101ff45480e4ba49b1feb3bde46952139d3e1d34d7da0124e8ffa05bd19698be57ffbd5c2411f01a0588898cf4af2b3f3e1fd83e8befe03806d91869eb496c8ce989761da7190e036eb2bd14a8f9e195d5ab8a1b2b11dd56a098c1e7ec6d508856aec98b74850e1b934600b8b7d33cea5f79877cb9b1452a2fbf5fe09651c83c2b965aeb496a2a4edacd4f6f39d56cde44c2f99c2f0b548501220f553a1ad14c6d8a970d1cd6dabd4356568621d22c70dbbb21dab61c10876e34fb20d3f012eec956cdc9ed81c98e2810c218dfbe1de709ceec9dc2eb2590d31fe9855f8a1d14849f9df5120bda5a0392fd6cd93e2e8e5f80e6b30f45e9b409f9e251a0ca2aa8ab99394e9190f3c2cbd1bda77b49f9ac887e7ceefc333cbc49d080726cf373753addfd13fd4204f12c07a21fe2ae5d513eff664c0ae4780f4d4f87a807ec63efe098e7d196223276f4564efdd574402c77390d2cd72f4785501f89175f6d38768b6c77838723cfa66d42e3556077039ee8fb363b67c174fb70f78008229263350c14b54fd9361a9cdb29fdc57909c757f96f9f2c13905f44c3e40a16a92b0fe509ae9cc3647afeedb032464b176b6a1afa78df4fd6bb765e37071172bef2b6d045b9a51701d111b60d0a639c0ba034d5c6b4c146d079a340fe53e9cace778a995ceb2d39f302f066097eec6f65f775a5e803f10af031dcb3eecb2bc4939f478c5fdb96e0513d9ea90ee2cd46ba7fd45f88e8c38a23e06fc5b2c624708a5dee0d00bcd976a8f75e35c80caec5531ff4ef8bb735cbe7ffce86290eef23248b19272692b758bba1de7a66c63a58315e48f5b127849c759d185908a730f1f29272003e6491a0b4aa9446da297338e04a60bd5f8413778aa08cc0d146ba76a5ebadc775af2b0b3976acb54de8910417f857499d8395be90d207615dd061317e5385b886281699e484a7f958715dfdf3ec30d5423d94e0d1657a24478967513fc741fce01f848f9fdb8fa407b7cda2f7a0eed64d9795a2bcc9e12c1d09b4d71cdc9dc3fd2ba82251f0a9fe5ff32732d2306900184e4296bf4b5b92c106d72a638c5f6713f49a7099786b32ba7a8081aaf0ca40f9919e0645fb255c8a7f4aa672999ab84a19b9d759ce478b7492b48a83eb9bde46e7c5ea1883d03487ba01c8a9c4c798a765b18b311115d02911dbaa5566190006ba40f5ee86bc22eda4ca3d0e8fee49b1a61c4057d95cf797c30a7e06d1012c1af3622629de1765d3bd928df0cb9cc7e30299c5148f782af4871556a0ec4358019ef6a434ea3e0292e97c714fbdb3ab14837257947eb7adc9c1d682123a016432e1eea5afd039bfbade397a9360b674832d2c55d521820c0cbe68bdfbba6eab8189aeeec781362fb289883d2a2fe87e287b8d940ad6a4136b7b388b38b0913f2fba42dd079cac04a071636b7e5bca67b44860cdd9e5f9cd77f07e524e9491addac1c6a66dedf5a4f814fa54eb9586bfcb1a6d4a1a166b1074d28a9915167ac4cf279e8d22555df57cfba8bde251483d9b2aef08a180ff74edcbc1bc2219f01fef23d77fcdc1d41ebe683ec96a75a4784945335736770f63a5f000da542958558b5ee375c1c16a109d488d8b17daf2450f35e0ae08fecc139bf8d5f51f1d9a1cd738ac3bb1e91a3bcdbf79c6bcc9a09eb11bc97a7062fc4e4e1c2e796241dc42481d3dc89b31d2337e8cf727c43dd393bb738710ef7ff96521dd92be410f295c765a823e1984e63c534d5f040753715edee4c3f0c78cd468eb9322ae8d5aa92b88bb172082cd08148a8d208d21dac81f0cc516d08f9c0b7097d91bf73badf049b62085328e347e20cd6ac26c64be5271f4761a16ce90ec9c58b2b71c998404e1411f1a1c5c6a6fcbf260eb3e325d1f70132b5f41a279b082712005347fc7d8a6a960ac1ffefb33de83cd6bc704eedd8ee937487635b696975a7156473937d7c301579c4e531170a6d109d50185693d9dbea24781f391fdc1baca492f00867d362797392af50da481552b86f323bd297b6a0cdce20287f0ee6119be14905ec55851768ef95d50130965c6877ee8d91e1fe19fdbef7c80ef7f93968a0d717c354f071bc8cde4d69c84a6e876a261e620a0f7c959da0c638b32d58325b13ddc9fbf566e1f411edc9b38a2bd031a7225551c4bc596958b1c22d5ecfabd2c09448417ba8568938a1cd02068d4ae3e0821dc96247ca6b704a0af99acbe5ec66b28b7c461da48743ccf387771a15eaca6392341dc4657d5c4c986b0648e712ec50f22e3d68b272dd9c34b63aec5686daa5a0f9bd259138b6d967cfa368c04c48657b2de2133b4c47147877e080d5588b09ab0b19d947b6554aaf43601b1c7384707f3091331a0583abc41bf448283eaa4bb001a44836de63e66eef64b04d82ad32c4369bdca012df554097e493e77e1b26acd103b564b6e8134012aec9cdc52eea80955a76d1beb2cb87782157adeadf2ae6c6a4b49c031d6769be9b42e6f85c8c5a6d61947f931c321b45dc34822c8523408c77bfe32048719537361fe6a1c9a8f3467cf5529dd597e19285304c716f9144debdfbeeb16ed742fa17440e02cdae4816699faab22cec162054df5d6ceb6394cadadf5d60abfe5c1dbb3790e4a98bcd9a84f6d4aa8e5934d80b40d8da632ce6640ceb070ee6034947a094337c013075c1a1267a95c820b7eb5f2aaaf20736f09502faa043cecc39f2ce7ebc0a14f846e38fbd514b935d2a46dbeb778223f20694985d27273a9be7e1be3c7dc9b8af87c58d35f4cf6559f48d27cc7eb1c050c76d85edd69995ea3b2e54868556758014ea18e18c11db61c56436ca2ac66260635d927a72cd707ff5e533704477bf9f578848196e311369842846588febd3a229d0b4fc04a5848d98ca55c3996e34d2154efe73a63f052da1ceb72bcd844dad8a4a4546cc6f94b2029b4e2c8a65d2b50673668e7abce6f054d50145b744b8103592bcb4804b446e1b7f4910843f5cba5a34e5b17309eb287c39bb98f6c220024e7582367d3e5e83737ef64944437c9d462c94f61c754a887ae4e5f1d2d64497d2b7fe8e885af00e8e8ad2d998b921a654616866e492a32742f319efef91df3f2e3d2697a4a12b107ad94da1d64ee6c67f0e9cf5aadae3eef52a22ebe342199cbcad564cd11685e0678ea3c91bcb67278ae4a6ce5664e39e86c3233cbdaf812516aa824754f6493cd5559848a71275b35f503ac84ccec4fd172b09f9ac40543a54059eed72f77eaa8d56645986ec8767e78c2df76f33e549b561b977fc5daec7436735a46956077b661fd05dfa124fc30165d5a14d9215e75c3134cae2a7a8fa490dad2fa745003c2d74d83ed13db927f4dc5cfd856c758b39915ccfb695c915c3ec5f3257ec38a0ddfa1401c3527ca271c856f2b00fc4f44416f7a387aae1e88ca212d81a6b4ca1e61c1ed2809e41e78ad8fb170ba1e0b138f061fde62eb7cce2eb8ae434b37fd4eb78b85990e7f6d21b32b4cf9dc57fd9b46fdbaaaf25139315a99419cfca963b19c3fc2923c041bf43ccc6147c3f9736a162a20152ee40effd6a3a29523d77dcb14a70b4ab512bfd11980e30bfd77304eec045d50b5923e22def0c83439e4d0326d9a20e53c43797dcbf17014f80ebc2b66fa6045a8b402b7fb182b43bb8ed6d569568732723b0f7807ac79bb676f35221258fb1283bf7c275b2872f2c625b7e1211b381454ce044a3e8a634488ece71e6fc58b84668aa744302b8a061b5674cdad160c2d9ef600385998c9f002fde9c829a6be84fd27b8cdb8f328064210918f28189e0dba18535d978efa8a8157cd5a477db7e3c909a54ae886008a65ebdc3eb3f06b89ca21ac3981d064fa15f01b1ce801a2c515af3298c4fd5979e6a651cec9ca50476773a755f96478397dda65db9fc32b2166dec033bb46fbad0edfd03f3c543e144c15dbdca9b83f2c3f0d5357cab1180472c7264317b319ad50dbd476b8f6545d86e5e399cf6177461141ce2e438db3100a0bdf957266c9758f7039817141bab0b3ea234c317554a1b30081eeaa6ccf3406a2a3e38d0376d2c50ff03e770be90cc3bb1c05ae9ab546e21d5f1cad5a4df5b53684789e534f2983bdf41bf9244d9594e889a2eef8a64789b0e327d3b48a06229ff0e48d669cabd64b7d0aeaeb4990571e275c3026a75106083b32dd1f33511877c7bf78fa415243d59474044bad21c773e39bf48619a7bec8b55b951b79f097cac697860b20c09bacde7a5e8054774db8da54742c32264f62246ad1945be13f1f7c856810e9205fa8dd797fbd4def035107f85ea309c1565f0ee1fc1e312d0bf753aed6a8b7704d8a1b2e88703511e6ec48c17ad33cac96aced306c8c08dbfc12c242d6fa52c4e51faf4cd3b331f57544f371fdfeff6c2d5abd7a38ef1abeef3a003aaa7ad6d4dbca80cde878cee6c46429d86c64c73671093e9567cc807f9f3cd9dc501878051166220c2d90915ef8e5eb46c0c07befd7a63cb38f5e9b4a8f32483d998b67fba733e7888c6297359fd32791beda81f7e8cb5d8ee05124b646db4ebee1e477c86bbbdc8d9f2151d99b8e6f0f23250649faadbe7ed2642505d7c89919bc10000000000000000060e171e262f", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 4, - "comment": "longest context", - "msg": "48656c6c6f20776f726c64", - "ctx": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141", - "sig": "88b645448a1c81f55c81631d057b1ca1fa8bb42af19f1c2dd2bf12594f23b86e17e383aefec687503d0077658497fcc508c8f7b9b6ece29777cd6625c4accd38e27cc4822ffb61fef18380362d29ec040773c9a2ce8b6dd7a1dfa233b76774ea41c766915afa7954f5e24f992d1dba4862802bf775d70c422100717a0e4d9ef9e6d217588cc6b9e1199aaa4d89e78ec1c7ba567c645538e4e6cb7cbaed4dc0663ca36fa036ec1d4334249cc6183033459c3035b4b56f0837f15ad908e2d9560b39e13580497ea8d5e8ae5ce71ae876b5b1e1deadc205e8bec65a724eebc1534155c1f81a93fb5bc6d00df71d8eade2905942a4d6234ce72bec2eeec3edfb7da4a6cc67af12c616bc63dbc16ff1467f02fa0c99a4b135b6a71e37222982f91cb466ea920fea4a729ed09d763e4dfb1bad062ace603c65f952e2df88c6ed63fb344d353265f21aa0e5548676c5d4dc24ff7f1ab1aa91ee19e9d0e72599c85f51fbdbd4f7d21a35ca87ceb19cc9d28df071538f34382fe278bc512f534cbc1f747a4497bc5827de2aa7b672bcf44988611c2e8e8ff88ec64e4ea101d47c88672b1794c1af23ae4317b6b5fd2923ebb7c25239d9efd86489fe8177f6f27de7e80833a344c3b907300c73ce9f9cb2a39296c59d70e180f14261a51814ca7c8117e33f800c126df8c92de498ba9a443b480c9f6c23d26e73b0299eae2a1223756132e3999cdcbdd436a9fcd5073c3e6212ca0dd3e734e355567bd26776526c15dd1b2c2d09d8604da0c0cb38dbf5fc4615d9d5a5ad217690308e34f549981656be6b144de153b9a428a314a19549688d57c8bb4543f12424622e1971c3b26772b3e74743d668c9008debf1ddd942ede5206ead676f249b93a324d60bcda8be119a61f9bec64253ceea1fc95ca5235ba41ff8814f83698bc3188ab802f2a6f33b25412a729635b7e530536bb90972750ec905ec1336e613112ced0a3e68427a2888b4135f8eebe4d4a9cb104627ddc182f319bf0586b82a9edbbc17c11abab38f2add065fceb1d419259597e4ba91ec5d15502f3253bbeb75917b2fdab1c8457af97ec864263d8dc501e9ac754f59cde0373efd9b18463a27eff11199afae22711c18172e077a0feb457b08ae8e3bc6614a2603e95eba9eb230dbf48c5173c1893268fad24e31a5bd323d5b224c0a9fa5fce2afd61178390fdce163b4ffa1d8aafb248ddce727070677310cfb36695b8846c4a32a9973c88ba0e17a1c26d62f716858200752970ed6490eff966201c9ed9cf223ce714eac732d52e0f63365c3b2789bf8a09642475407da12fa19394c55919af3a02d31e26f4270d71eeccc5c5373ae35d1fd9a07d500623b1827c4674287083cecb466f584e31ec933bde9c83c57e8a90a141eaf4c456688f8ca1353e64ebc7cce779241df3e34e7353cdd3af446812c4448383efe1613e5f1f6e9c08c0d5971e7ec28874d7865e3bd4cb1fca0f7ca1fc499c718a8ede6f91a8232991ccd78f918ada16271e84c6b8b679a8d5ab5f7a07ebc82b01f58de7a92753a028679ca244a72b13eb5ed2910da55a998c1f427d2403d33862b05292b1c0bec902b51f4efa0264e6295318c6a44befc85e00ca887350ad86ef9fc45a4a01322522f74b7ad63abc6c08da9118319d84c0b2164c9300feb1f2ce80de5a79918bae083397d42a9f415a40f0347d25c82723d62b1fe52d02a90be1cd7cfb5c1732d644db047eb48b50ff38ca74929edda7385cea85a07c798cf773d4d4e29efb70125307582752001d8f3a4ecde8db26964d34f5563a6683d4939d237ff6a68361f0d2e863bdd15c39637e83efb2b75902220434a273b3ccca148267aae092d8a2b0aca3ff1b352cd6b331bb63ea3e69cce2c86174c8b2e0d061a35b067f2fe7d9999e2c1c07f07b1e98246af36403b2a2bdf48c7e4397b3045303dd8e3af1138389b0967fcd146124fcc97fa524e10afb0ddc1294b7543f77d0dbf0bd845b7f9c36dd91222ac30f89d59d3d048949a456b43338cb1ff1b8392b083fb6fd71797cb21ed52b94377c9c69d90111a30612e65aba8e85fcd95fe53b49f18952380c1a9d9347d21e9a00633bb119481d7292ffd25ec5d4dd842ba2c775757f1a5d26025e4156f3db85741bfcf60f5efd580bea6fc617ebeaa78baf88a0db57b13bb5dbabb9cfd6c8a56b635ecbb1fba800a0cb30a6c241096f6df1f04bd44b3b99a93545c6cbe6986e5260384824875a4ea2ec84e6574fb6f08103c4da71c6689cba16cd28e8626233bafb4edb9ea07bd02676351d57261586832ad67b87ad61a59b7e7b8519e85ccde56722a6cd2a7649afd5034f98f1b9c1cfb7d320f491dc90002bca428a88cd063a3b30ef09fcbc5d6a4ecc6887e0b05b4179c0bd4d8f4791c5cc6a801b4c54e6568469b22b52638a5a514e550df53aaa1ae83fc9999658f86ee16661e301626fe77b064bf94b00fea4b8dd0237906fdfc6cc5294e526528675dbead67c7a4de642af3d9311cd8f2ad66002bcbb35668da0b8f2f02feb11b1b89c264cb5a088de45093cb72c4e6d54ecb5f1ba5ceeb2b95c023b412ab52e77338bc3859369fbb6996a35842b578a3d844d1facc6e7ff7bf31959fb16680cec82534792913dc2aace4143f412b09fd09aea82ae48f2d16323a8abae6527967058e62311f3458ec0f999a3ecc087501b40a0bd25f6fa6d126775bf261d0f3c4d428dc78c6b594bda8426342728ae4035e8527e24e01ec3ab9193dd2a72c84524aaa685bd3ace318dab3be7d89eef18a887c772242895ad9d555c444c670f2641c462295ec0620eacf3ba75b8fe914f1be38dfd9d12b501e09f931556c8798e1a40806c67833fbd2fd40227e3854e6af14a7b9b300fdee969e84c76b9a142b23de64c27ccdab63394c6d39e66315ba1a376282e8f7580ed60eddf9ce0724c57aadc7a8ee5b491605ddcd4c4949cfd6cdc0abbaee10238d57b5dff3b38d3607e8780d7bed5f52f524ea06a94ba7e2ed980aa132fce04004670d520215f715e2ffcae2ce336af653a754e53de4ac26feb591e923a6a5cb9aa97e71f52d0f4698f02eeafa894faf56121d380e24d2d82dbd5687e162ac7e93c6d97029660485d5db8c886480c6339df8d7724201a80dc54cb9637767522e50e5ce696ae29a04fb5b4b6740bfda56a9b80b507bada2aca4264f0de6493e6a7f631394838aeea1eddcc9142fe31558b4756f4f2745f31b58c2c1dc1b2550cb5bdea478872ab91393048a908673106690c8afad8096bd928e32c965bdcc3a7cddc9411cc36faff3d9d4e7a5afad0d0c5d3de867b990490edd8497f3a03ecd131e7424d5b0d29543b3cc7ddb6a1522372b11de1649046ce787f6fc8219b0a3bb508f1d6ec2981066dae16fd127df52cb9055a139d7a68f0f4bbca77e7ca8ff6902a4d87a59671da1b867840fa0e07d8e3667253a41525ed18c679c74cc2fb1b7b00ea98090eb6f2a24da3885efcf6fa31c66732614083d114e7a2b0478184bd801fb36e79f670eaffedb9a3b56d7648009c6e4c33da1f9888b54ec108d21c68fdea0bc60af17b6958479f91ca9685d9704553d2126c3cd240deaf5a0aa8bfca0e37899af660fa9fb5aba33ed1a5ea5e388015b6cfcaae014e933969623a66060f5d396d3bd0793ea79bf9189ba24a36c1b79dff7bef60f921f27d2a46874b282d5ab9839722b495fd6b0ff494f3410e0988006f8b4bced46f7d0f41678097c4f8d5b690055d47c37a887e0fdb1ef45d90be23f59d637f27bc13f25750b83c005e68ce669fe15e47f33b4bb989f043fdadaf7c11dd0e652542d5103ae73d41ef574dd82f0a1144508076276023c91adde4b126772ef620b6450bf5b25fd29dbe3a529014b47243328e309ff4245a8aa667408ba5b4255879ba6bfd4f57cfed9219f88c7656838afeb58aba3d86157a4d1385e7a29d4db695702566f424f3b84f9464a1de1e5ead4683b38f672cbcab96b2c23e796107ff5bae2f63418fd3ab622868312cb1aa45911ebe5ad6ceec0d9138f1e10410758f024f1b641dc099e5bcc83fad7d21d503af50f7ee12da5ed1883689d8dd0edebf6085d90380f5b55af179ddab5df7673c24a253bc3d199d41a0e860477eb1055ab7883528c9602ac748dc1de5cb18d191db75f81eea0db9949ac34cc284643b2f84b5b3cb13369a5ae40a4b59a4462783c66df5c84d123fb6e171ec2f7801622b5efd6dddf28dce5ae844db98e07a24295ec20159448e2fcbafac66c004f6f9a1c29ddef7d500d83e783443f192c79205efebf0c104f56c59c59ce7e1906c6c35b78417f1d9faf94aea8e9c77d84f1e021b40423688dad22c209c9615f0f09557ccced493c06f4b1a4bb841adcb50070eee4d40ce61eaadab7294051682318d6fccfde090f447303426949dc93f2aa1b78c70e68e7409969e74aac563748827a232cb8c277a3a71d53d8ad9044e78ee4dacdfd8f31d9def44a9cf36f48f019f7013a2c622d19505236d18b3ac6ec5eec629b801783979f9bad8ee2c363268689c037194bd8cdc3b4db694e443328ea40122235f7809d403910667d99324899ee1b5f8890d65ae93d5a899fa9d5ddf6324a99bcbfc3f1688ae4000000000000000000000000000000000000000000000000000004090b131a1d", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 5, - "comment": "context too long", - "msg": "48656c6c6f20776f726c64", - "ctx": "41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141", - "sig": "d75d495e0aff760275e801ab0c6ed1ac7f180c51b112122fc0fcf303a999261efd3473bb1e46c7298a2d49b2b11934301145799e58cd91cb24f052e90b7bdc1cf590b6736abe772f211d8deef50fafab63033bd04411534c233de584ea1bb0a73d6cda890c1f0206891d55e9b1aa3352c0365dc56449356732e74b599ce33724ffef2a97897ada2a37cfe178a3ee47f8002fd2e02873afd935890f1e31043a7d17aea570285b94024c7fd8ab135e515799e1b2816d4131e3c5a5e1199eeee82f292cdf3a1c290838db1c46baaa2dc75c379342016b06ef1768cd30989bf5297ebd57adb6d6e0b4edbc685a2258ad3393c555bedf933c566f0f848960ab6c2036b7a1eb971a4519898e2b25d8a9fe0aaba7620e580d1c1a6cd6826b70c155b4135831986126613c2a78cc4ca93d900b56f77db9c7214d46420ebe9be0995f9615a73f74b66a4ad1d5570e07f2f9a690750852426f1ed0e61c3c7467ef8af0301b4e4caf01b7eb96f8ffdae739cae1ccbb39631520709e70494c36f9e15610eee5b479eaca35028c1f7ae1da78e4e9bb03dc8f228687f414c4d3ef427fc25ce44c1a06a8437e12974478d84bc566f752a0ea08101ae60c49facda27481d52038fefe5eba5db3dab643bcd7b00b8f9237937bba76df5adb3139a605bf52ef93c2e9a56631b0f86e7be961e0b1e42e8ea4401be99af9b45b01104f5b879b81ce07ac4732eb5c937e7a017c430eefd4cc8baeaf57eab48042f3fbb2a290628873702a9196cc8fa793466e8d381f28f5c050deaeaced44889520af258b897e5427c3deb74760e9557fbaaa80d721f21792a5e8c97e536ad3319f58d2f1089a82e35aa77101aa8e8e8b249a608cffb921987e16dfb2a34ba8590f0c9c2a6c879c59fce2ddf8b2d9747136a81749698b7ba4f5d56f12718dd7c9e296fd2fc52a0a33c9bc7fa5632cbb8c73bf0f4ef427c28aa7e57ad5c069d4b68095c539b1f16623aedaa1f30d43897380cbd1d8b9f6699a38c7dbea893457937aca16aacab67db5bb60195dfa1c0cf02e3d368854ce2191b59b05c6005a1fa09b275966035ff68e91f3c820d8f3473748557904206ab6af36a343ef93e3e121f9490e8770f0b2a703b932b16d4ea19629b7c2b26bf2ca7a07ec6fea8cfd4db85d185d39731b0f3df6cb07d152cd960640facf1c3856cf5b47937644ff9ae17f2037bc7b2a31619273d012afa35b331f78cfb50d23efeab8525be11e313cfd9ce731696a558cce05a68fff8c55bd103af1b6b1b13c8bfe9bfb9d0e86da12b5d9d5385829490a89bdf4e4cbae80be22ffb624ef729917d849c572c44e35ec5cd8354d770bffa5b031ee1f2a76b077b241767f384092a21b016b5687752f23199f0a09e5fd701090fa9c289ea50d26bd3a8676f49b29ba54785b3d20431cfeb519ccbbc0141266a77e7d5bf4bf3299497c8b1d1b40c2f00cfcb29c3a99876a43076a89a13cc58b5af1d72f87e1171d2b6ec9fe4fd318e95590cee63f1a2a6a2090ba3eea95061222db4c8b7cbffc10b450bdae10c0f82fc6861cbd24b9e4d18e4a477f7491586ae23f7ff10e1963a874e0ec97779cb33b4d3262c504cc59bf2c518b7a6de0744297fdbafd8be05bcda2b2e8fc98808594e2a204bb72aa9a425c493ec3433ef5af84208c7c47105a7ba7b936f189a64002a0bf07aaa16b449f79b32e7bf238fe72ab2bdb3e3b2a64c6f325e8486318c50bd905d23afd2988cc92ec26078b2fe9e6fdc5e27fca279c5ad535a70e66b5a55efffa1583b8011b084bbb9b028d2154f2aeac02ca66ec8fba4cec93feea0291e0017c8ec14e49c0cc2e5eac9276f64ffff107dfdda08baa8aa43df97c6adb792e7b781d2edf79763b9656794f0910fc0c17c45cad7f7173401da1f7fb9697b571fa6bb23fb687b71dffd21092e78966ff61fd385f0a236c93aa2d550305e183eca91d284f161d5d2a18824e7148c2c615e939fc4299e84b686e3577f16e8489ec0cd1ed80e8edceef398d007957b571d6e1680e641fa1cda305f993b92ee77f5dfa2e2b4bacecebaee0085c1c87762554c76c5db6d9515647ed615b42366c05d77bd0c7cc37da56a52374f1c4a01ffdbb50a05956f5a5c9082b1de4bf9e7abc3bf8f6bbf983a49108ece5f68ad07b3f309757e26e9bee76ea44223210422ad192f1d1102cbdd0047f07146be860860c28fbf5aa9b401b96cedb9097d9c95fa71524a5827fd562d600655e7ad3e4c592c67faf8a71dae5094e4beb188197ea635cb8d9b25f91f5df2e192b55d991dfcb7d696129e956e13e5518cb7f126b5d0cc9e87c5ed00c2a15eb0d343f283f658001f1addef1043ec46885099278477de6d329506659fe29f7d192feb93a39d3dc8d06913d4b7b621c300d8c01efbc37740d15d6c8f2087c2db3a2f6dff819e8b2af5f5ec52718c970df9e5694e7390cbf7999d5c739845f2ca98d5a4789887f0a6648134c518172ff62b6e85852dedf351d3c5a2727c7e0a9460d595df70961730ebd283519668cedd430621b9af7e04a54058dd6c04770262a75455f7c5f477a4f339ab6d4293a02eee565e3c7ac464db588a64d0bfe1e1b9f3f1977ddeb57e20449153da8881db0565a37be1506f551b8d0490353b799dcdf3003c4ee378dc16d76592310135c3879c2d05e69ba1f9aeb58c6187945617691e5872a0f322506408d5434818cde200e60fb6f40aaea77b94e4c30ee295e8e49b26ddc69c54b5f12bae4186b2e7e886585f0cd14b6475fb37a217ae79f87ae3303d67968f3ce82a40c6590b6cb7a6f764c1f6f69642f67459fa1f53f04eb73142351f0249f4970d3828ed7cc6f7cbd74fdcff388b98ca3a9747d1b70de11694a5e8fe1bb81f37445c6b53933b47a1102818ce623f914be67f51da77f8d666d6d77162aa323c5673749bbb01555d3d204de2c4053989348fd2cf61e185ec8a453d91b09d08a10ef3762a630c53adec121af51958cedba5f82b8b0ea755e74197a61a09c7350547767c2ece07dca5737a97b885bb1dfcc9030838acb4c356224af7672ef9cc0435b404be37f74ed3f042d00f05be35781e977abbbd46e594831c07b3ee45c0e170f2040e543743503262a59c9880c1603c79f316587cde475d6236279a194986db710216f1169a6c7b42e987a9ed7b4fb4212b8bb25bee469ec96d0af41a2e794ab54ba72326069cacf2f5e49b2eeba2ed0177c2ac71816d9f6e2c893fb54369d901e6716d2d04fea85c809cdd9d2fc4cdca6ebcb10d810f764f1792f4a557652da371a3ad6f039d14bd9f5235c8b9c5b5a48333c798ec000fe44ad6c9e7c9e5f57d406e5e8ee8154574b7c76a2f7521947c54a67ec44807622aad566df4d463b3bc0ddafd0fc017f1392cdcfee32e96ea8cdc42cb6e4587cc72d03ac789070c210a1278abcf286e23225ebbdb5bdf917938047e9ec980434ea6566d3aea655ca8a1ea9651d2f0c30169c29cb73a975bf69510e1b6ef8db72e3bb7892e2991488627f716fb7b5ff194757de8a2479a4497f6da76a421b988534b78f8571b4d7c3a2493c2b7b8b02a07eb43fb2fb1d203b02bab2125e7ce41db5b1ce0bc2c7f0706837715223ddb0dd2ba58a98db96e79fa28b1ca14be60058b2ff7b15ae2cdfd38f1d63b77ecd0de4c6e0342b6535724231e797bb717111dc0f0714c40e786a55a2dadaf853bc3cfa324063147802dc2a3bd6a881d3072fb8addf1f8607a7b4d4dc8386c40593ee6e5651c90786077128c9f6ea10aff3fff1e524b3ac1ae1cfb2cc6f659f70c718a821b25e31d7393eb5f5b95c06f0958770cd1b3ca5a6b882aa5c3bc0e300560426c4194b00e4dff3d300c8a47f6c5139bade447b1357eee0164414d75379ea6f696bf15e7a47c31cb47fa4b5608eb0593ce58b61199955e243a8b12cf26e21e05390c2a61b562de5d70f0113f1adc3f3a4d2de7fd5994f6360a3566128104a886e27b349671087c348a101e6f6ed673699962c96f699fbd3aa37a95517a6c99d83c69c16aab974d144b3dae33c9fb850b20ed6153a212ab940d63fb546154a0a377ac16eaa58e97e1a1a5bb4c9e845ed098755bed89abe251e8898f3aa9fe22ecf8b780f32e741b59e4c56a6db067aae97db9cedefb39fe580af8f218bb13bebd51ccdff133fda9d696bffef58f0a46013a31ec1a75918ab5d8e9cbd6a79421ebaea74007240a6ee379f1fedd904e8af829a2dc92ced035f60e8831c73bd1070ad4d5068ec3b2d58069adc6166231ccde5a49a779340c52032cc9434fa479270216037807f37ad0875bcc509ff183c9c518ac22ab527e01eb5dfeeca74c78a400d1ebd2e0fdc1ec19acce8e53352b8ce154e2f671e930cffa1a3a388739f73824eb085ad54aac583dc0d2624e07da1e0c32f61dcb83e632d260fe9c453cb957ee54d1437b1c1c1c6f919916146fd4c91d7ce0e25ee7209fce21c7a6f77abb91dbe9c6d9e3993897965f1cc2fac0e4acb768eaafdaec0c1b1f6e16517be4a7b946f422e61896eb4a368297dd222b8a2f0ef0f80a9cdf168e5e13ef7eb974bc73768655352271e4c38eca8ac5210a4724e5ea0c0e18aa2cd101f216872cadefb05133062c9ee39567a868dacb2c1c43e4e5d6aadf4000000000000000000000000000000000000050810161f25", - "result": "invalid", - "flags": [ - "InvalidContext" - ] - }, - { - "tcId": 6, - "comment": "short signature", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f930000000000000000000000000510131821", - "result": "invalid", - "flags": [ - "IncorrectSignatureLength" - ] - }, - { - "tcId": 7, - "comment": "long signature", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b00", - "result": "invalid", - "flags": [ - "IncorrectSignatureLength" - ] - }, - { - "tcId": 8, - "comment": "signature with a bit flip in c_tilde", - "msg": "48656c6c6f20776f726c64", - "sig": "68da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 9, - "comment": "signature with a bit flip in z[0]", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b279c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 10, - "comment": "signature with a bit flip in z[1]", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5794e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 11, - "comment": "signature with a bit flip in z[2]", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55013efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 12, - "comment": "signature with a bit flip in z[3]", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c076547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 13, - "comment": "signature with a bit flip in z[4]", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d602331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 14, - "comment": "signature with a bit flip in hints", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3d3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 15, - "comment": "signature with a bit flip in the last byte", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212a", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 16, - "comment": "signature with hints in reverse order", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "0d0d1a7af2d4eff6d4af7435a634d28ec5d23595fe7a72cf76d30f1fe16620c64862e4aad54fb78f8ea752b1e43e4e5884d7226840beb36a76f6a9b1b7d50b0faf7b8463f57c66240e06a22f5f3de4fe35c1bc6b5e42ecb1c0758069223e02f42efdbbbfbc87b4c0736141a70e6dee41bed27fcfdcb94f4213a0f99a02beba309a93d343cc932a6fd67fb90d6de7a81101a678e6d47d8b1c8bd67fe386dca360be789555196e2ff8704c175ab60a8bf3c9f3bbae1ee5a128f67467d21fe8a62e5f8ad8127b8d7eb37e43abc963521e79d0f1ed57fa341f743246fe69d97afc9a13824c79f7f3dedd286f3de739158a0900c99d9c8e5603df109c25d993f634582c832a79c7bd8cbf3ba07fc4d9e9ca8c1157434515538285417e6424209173c6dafe54c37e4424de0f25454b1713fdc3e72d01a2acbeab4d7f60d17dcd073c60b0ad5252cfa137c138448c931498f61fdf8f449225b07e7e0fafafb1f274fe5cbaaa136e62362877f643c7c94946075e8928ec47c04ae54d2085f7f2b1ef0e46dfb31b9a19135b6cc9da876dace6f61c2766b463b24c0aac5068714e348dea399986c4e8b8bdb16768e7ab81e9ea13e435f97e35d268bb679071d5b99d0d2f1526833e8624b6e4ff1ba3f5af2b23bce93dc7c2c4370cfbe698a3297005c9fde7af66bce7c9ef68337b04d7681e303a824e00acdae2ee3eb8c3e7507e46d67a4cfcfa9473bfa6334f2170911bf2ea75a3618cac939d11d6a778101e033cad958aecd89feabfa19dc6dc73584917834ed6552966f7bec4546ab24c643db25722b3ba412de04e9195898388d9ce04cdd9343da69ac9b3d3155620dde4052e9e30529904f25dd6233bafd4493b66844c8fa5d831377dc3ff8829114000799801d46586dc2d2059f6bcaa43b899e089b4f3a5ed4e6a7f1df5b8d42fda456a70e10b2ae14630f27e4c7257f5df23ad032c1edde44073585c04c1231e085591771cb64aaf62febedb33df56bc62f4d126cf8be4332ce4965e6e67d0be7871d81dab963c576ad7123bbff510f282bf66c0c1ea04aaa05a7a4d410d0e7b6ed22025dcb6ceac78f377306e973973adcee776ecacaa560dc8008799b306d5e617b2f51159b1e5fe5daf40f8f488f077cc55bbefbe8f5a61c28ae2b1493272dc6a4e34854f73f74c3442d9c302f96b6e721e2956ee0bcdb9999ff36d74b8d4ef036afbdaea5f977da2b94d0aa9136abd6dc26348873090cfe3d4bdda4d962f9382576bbccf8ba227af4ca8e017f65b469d2e3d35132fac40cdf03bf8f6beee66fe9214e1bf684e0aae75e4141d9daa1c77ef409f56424b01acc7ffda11cb9bf64a9aa71b484b49b9ee82dd8178dd4adc91d8d176f83d2cc7516d2195917fc246ebdc0dba4cb5a54ac6169bacbcd79adb72d593fcc3fa289f1e4bffb4612ba7a3318e607b0b27733cc70a2e2b4099056731ecda3212d1719a6902cdd6a05bd70d389da1dd0d0b4f6c4968676fe33c6e32d791c85b16cc9f4289bdd09acadd9f902d9a91f1559bd40eb6b73da7a623048140f73454e4ccb4ad65038109f6eba9fa01b0a3fe1af228e2c4134be136db2b029879e101aa8ab264e554818450734eb5a900497d906e20d36eb3848b092c778054c5ecee767c00185ddea39160e4513be858bfe5c7c7febf97ee8e2b2fb477bfb10c11f3b756c0da1d87e3121ab4454016b36fcd8f6d2633c73d4528221974b3f21ed3d464d47bacaadbb4647320bf0bcde38b0a75b6c3aac8b72d3c2c179417d05858ae4bd72d9c16713f7c116dda3ff8164710d4d14964b33b00b268007f8cde2eacea5108fed77d7bff70273f351b4e160d28d02576dd5f3fc3ab264c5927cddb6f9a81b852d24842bd5db5c5f2d893b2f013fc75426ef2414bad1b845ba7833c88a8ce76fe2644455be2ac1b9d1e31791693fd65f1ce35fee9d17b42b444bf1277f2646a19d76952b3fa3846c3d258f9a1835a709fc21472b0f7de7a729111e850f27f88764b3ab4baaeb6cfc644b9b6a552a61a7286b5af8011ede05845cb9359232f02ad8b3605b00cbbd83069f26b610378055c004a456c7c44606125b7b076b3f955117e03eaa514da82a9650e8b9247902c5048ff776ecaaa5ea57df61d726ff1754d4b1393933599edc49617836ecf78cc7dd45750b666b73150496e3999e339243f5644d5a3e57c6cdef2ea6c967f8bc93c27aa56ba5352666ab6dbccec415f610bcc76879793935df8e594f5c6b80dc0adcea1a1d5854f447604c54dad61cf0ac91d27ef963e6889075163e89cdec0aebf32080efcc58280b705a029511f21d311c1644623f82039e096f7e1d2518928847abd479840b65cf10d15851976e47444d64c6d4425310a3b5efe9b584ce7aa01b1f79d6e3092486f91fe75288736e852c0132561a7616f21b7713ec53f0dc53432f53eb4ad778dbe14664b55553ba342eaf94e9f76320f8f658b4c5173ab938fbbfe20c9987318c1a5104efe41419926218d30b0c97a366e60f6d1240e7f601a1b119df36cda11bdf7fb531a27979c9823efd2a75c70387f0296dc7382f570fe59568afb406a48e7c13bcb40204c92cfe13b3980410b229767a5412a7db82845da135cb6d5b2f9f5b22518b2115dfb02115fa1c4c3177a55f5c194450f0f0a518df7755b0b12eb412f5f6ee2256bb95d2985bdf1257769718de9b4f4281c3eb3407f175c0b43fee6b94b00875dca0983ae763624bc4e84e9a78f778dedef5eb078ee87a34941005c15cf42ee05cafe098005b1770ccce4e59d9d3f6eab9fb2673766d9b70ac11cd6d8b9d00809e58a046d95ff62e78a8e5525af54094c907019ec661600ec2c4ce5337371a1daad0e37f3a5cdd96a3d985456a588b5c1f61f36a33c6444c3b67c445bf95e9035cd4f77191a95a7e4c20715e55dbe43196809123499148a930321e7b2cc7809cf517fc4b2b0b49e57cde4b6aae620fe8cd0b38358685ab80061c1c126a1f3a96ab34fa957236cc6c59ed962b3bb006a1c122da796bf6bcf7dbeb64f4339c63d3a437b5898be19f6ce62024cf9b9c89964569f176fb697430e553a7c0936056183223fdab2f910047ad5e64098a44a2edbfd3007b0b5e4a5d1e6ecb44f137dae2dfc45e96f03e75c900f3f84e2653efded35a3c8b27e310dc361c0740524e52a1bbecce57d59c4913313e62bbb63c95a93512bf09228918bbf921cd5c62b8914b7142d6abf8d632c3ac44ebb6936c638d56cfaa7cee463838a921398acbbcb44bce621bfd81fab34a8ec33810eeb89fbc3cc469990089d2291e1e873b31398f2799b8d62d429b998422ed634bd7a6de8e991ba8492c001fc5df8b0014fda377cbc5ac74e40d50773ab5c2b4d08dfbf3cca590a77f4db0380fe7af822207aaf99c38676327ccd9aad50b2d4db5aedf74b1cdc50c484d455429352ef0aacedcd9792dc26c66081c28ecabc445b6f1f547a24403e18b0468c8881bdc3e82f7bcce254944271c3ba06c80555c8f3d2d051fb6007507eadf8fb991f45c0c9e9ff08838a425a96d72fc20d642c2eef45b4fa43e7b380d8b6648695c0b9440cc66665435ffd3df10fd786f7638e13706f6c5651dfe5f125158ff3d1da84cad23129e11d79d0f95548318b1c794990174daa895e4b984c175136185be534ed6bff9231c215fbf6bd297e24f528cda523d62b44aec15fdfb36281d804625db07567fdb06779325987f69f16f19df737d5f65d1abadfae70a1a4daba5a87e4ea3a09751ece2ec21dd24f719b1f57e795819689c8f2e83beff593735825a1ff8e4e4df9d031dd66120dcba07e6bfbf1b0946b3585a5eb807c1632a75353e8f7b8c4f8ff0af978afe2bec80d3b94917773564d7efd92a79cad26360b599be49bc657b132b25f459d58166110fa626cf1731be419105b4bd235176d60efa939fdd8dc213c695674bca27f161da4514f646f33557aca06189698f2953674ee73be89e3fc4c014877c6bec370ca1fe446686200a94ded3382c4f4bc58cdc12c354a486463959cb91c2ea0ae965f912364c5d98acd40ee312178b479b540875fb2a0164b7134564bf7fabf59add993b08a904452152031a784cbd36e19a47d4c9371e7774d3433fecb5d072d059b01ebd3279ceeba80b356e3628874008d801ed74717c70a93411603f1faa3924414665a95c475ac42de8d616de8be5c00fb90e5ad13079e54d1c7000905b62742ed70555ec406b49cd4aa6ea68342aa7763530b180e4f790475eefe1094426b7de9e0163a4990ea3494909c6c6de6b7462d70c8f2dca3152d81c93a8c184b0c54da7fb604f835df34506731774e6b8f2361586ccc17f35c8e21795ccb68a5cd73355c98a17c9ae35ed22f6c0a36c4da30af96ce7347375144a80dd851fda4971f20e9d6d18878d74803b577af4fa8f34c05b380acbc5282eb63f9345e4dc1f9f0cf8808a204ec789ed31ac9f009790d5c9b7d744ee3b29d911014c12b53ff691fce0ae5d53dfe1c7a367e694fcd2f688d46758ec308f3f9736701dd825153df883c0dc539c9dc3dc7dc9a9a35f453c306fc57faf76451bef45889e4ab0abd6d4acfc7967937e7e080f8f3935d47342219fbd3a27e1913f2eecc972e2c11000000000000000000000000000000000000000000000003080b131920", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 17, - "comment": "signature with too many hints (causing a buffer overflow)", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "0d0d1a7af2d4eff6d4af7435a634d28ec5d23595fe7a72cf76d30f1fe16620c64862e4aad54fb78f8ea752b1e43e4e5884d7226840beb36a76f6a9b1b7d50b0faf7b8463f57c66240e06a22f5f3de4fe35c1bc6b5e42ecb1c0758069223e02f42efdbbbfbc87b4c0736141a70e6dee41bed27fcfdcb94f4213a0f99a02beba309a93d343cc932a6fd67fb90d6de7a81101a678e6d47d8b1c8bd67fe386dca360be789555196e2ff8704c175ab60a8bf3c9f3bbae1ee5a128f67467d21fe8a62e5f8ad8127b8d7eb37e43abc963521e79d0f1ed57fa341f743246fe69d97afc9a13824c79f7f3dedd286f3de739158a0900c99d9c8e5603df109c25d993f634582c832a79c7bd8cbf3ba07fc4d9e9ca8c1157434515538285417e6424209173c6dafe54c37e4424de0f25454b1713fdc3e72d01a2acbeab4d7f60d17dcd073c60b0ad5252cfa137c138448c931498f61fdf8f449225b07e7e0fafafb1f274fe5cbaaa136e62362877f643c7c94946075e8928ec47c04ae54d2085f7f2b1ef0e46dfb31b9a19135b6cc9da876dace6f61c2766b463b24c0aac5068714e348dea399986c4e8b8bdb16768e7ab81e9ea13e435f97e35d268bb679071d5b99d0d2f1526833e8624b6e4ff1ba3f5af2b23bce93dc7c2c4370cfbe698a3297005c9fde7af66bce7c9ef68337b04d7681e303a824e00acdae2ee3eb8c3e7507e46d67a4cfcfa9473bfa6334f2170911bf2ea75a3618cac939d11d6a778101e033cad958aecd89feabfa19dc6dc73584917834ed6552966f7bec4546ab24c643db25722b3ba412de04e9195898388d9ce04cdd9343da69ac9b3d3155620dde4052e9e30529904f25dd6233bafd4493b66844c8fa5d831377dc3ff8829114000799801d46586dc2d2059f6bcaa43b899e089b4f3a5ed4e6a7f1df5b8d42fda456a70e10b2ae14630f27e4c7257f5df23ad032c1edde44073585c04c1231e085591771cb64aaf62febedb33df56bc62f4d126cf8be4332ce4965e6e67d0be7871d81dab963c576ad7123bbff510f282bf66c0c1ea04aaa05a7a4d410d0e7b6ed22025dcb6ceac78f377306e973973adcee776ecacaa560dc8008799b306d5e617b2f51159b1e5fe5daf40f8f488f077cc55bbefbe8f5a61c28ae2b1493272dc6a4e34854f73f74c3442d9c302f96b6e721e2956ee0bcdb9999ff36d74b8d4ef036afbdaea5f977da2b94d0aa9136abd6dc26348873090cfe3d4bdda4d962f9382576bbccf8ba227af4ca8e017f65b469d2e3d35132fac40cdf03bf8f6beee66fe9214e1bf684e0aae75e4141d9daa1c77ef409f56424b01acc7ffda11cb9bf64a9aa71b484b49b9ee82dd8178dd4adc91d8d176f83d2cc7516d2195917fc246ebdc0dba4cb5a54ac6169bacbcd79adb72d593fcc3fa289f1e4bffb4612ba7a3318e607b0b27733cc70a2e2b4099056731ecda3212d1719a6902cdd6a05bd70d389da1dd0d0b4f6c4968676fe33c6e32d791c85b16cc9f4289bdd09acadd9f902d9a91f1559bd40eb6b73da7a623048140f73454e4ccb4ad65038109f6eba9fa01b0a3fe1af228e2c4134be136db2b029879e101aa8ab264e554818450734eb5a900497d906e20d36eb3848b092c778054c5ecee767c00185ddea39160e4513be858bfe5c7c7febf97ee8e2b2fb477bfb10c11f3b756c0da1d87e3121ab4454016b36fcd8f6d2633c73d4528221974b3f21ed3d464d47bacaadbb4647320bf0bcde38b0a75b6c3aac8b72d3c2c179417d05858ae4bd72d9c16713f7c116dda3ff8164710d4d14964b33b00b268007f8cde2eacea5108fed77d7bff70273f351b4e160d28d02576dd5f3fc3ab264c5927cddb6f9a81b852d24842bd5db5c5f2d893b2f013fc75426ef2414bad1b845ba7833c88a8ce76fe2644455be2ac1b9d1e31791693fd65f1ce35fee9d17b42b444bf1277f2646a19d76952b3fa3846c3d258f9a1835a709fc21472b0f7de7a729111e850f27f88764b3ab4baaeb6cfc644b9b6a552a61a7286b5af8011ede05845cb9359232f02ad8b3605b00cbbd83069f26b610378055c004a456c7c44606125b7b076b3f955117e03eaa514da82a9650e8b9247902c5048ff776ecaaa5ea57df61d726ff1754d4b1393933599edc49617836ecf78cc7dd45750b666b73150496e3999e339243f5644d5a3e57c6cdef2ea6c967f8bc93c27aa56ba5352666ab6dbccec415f610bcc76879793935df8e594f5c6b80dc0adcea1a1d5854f447604c54dad61cf0ac91d27ef963e6889075163e89cdec0aebf32080efcc58280b705a029511f21d311c1644623f82039e096f7e1d2518928847abd479840b65cf10d15851976e47444d64c6d4425310a3b5efe9b584ce7aa01b1f79d6e3092486f91fe75288736e852c0132561a7616f21b7713ec53f0dc53432f53eb4ad778dbe14664b55553ba342eaf94e9f76320f8f658b4c5173ab938fbbfe20c9987318c1a5104efe41419926218d30b0c97a366e60f6d1240e7f601a1b119df36cda11bdf7fb531a27979c9823efd2a75c70387f0296dc7382f570fe59568afb406a48e7c13bcb40204c92cfe13b3980410b229767a5412a7db82845da135cb6d5b2f9f5b22518b2115dfb02115fa1c4c3177a55f5c194450f0f0a518df7755b0b12eb412f5f6ee2256bb95d2985bdf1257769718de9b4f4281c3eb3407f175c0b43fee6b94b00875dca0983ae763624bc4e84e9a78f778dedef5eb078ee87a34941005c15cf42ee05cafe098005b1770ccce4e59d9d3f6eab9fb2673766d9b70ac11cd6d8b9d00809e58a046d95ff62e78a8e5525af54094c907019ec661600ec2c4ce5337371a1daad0e37f3a5cdd96a3d985456a588b5c1f61f36a33c6444c3b67c445bf95e9035cd4f77191a95a7e4c20715e55dbe43196809123499148a930321e7b2cc7809cf517fc4b2b0b49e57cde4b6aae620fe8cd0b38358685ab80061c1c126a1f3a96ab34fa957236cc6c59ed962b3bb006a1c122da796bf6bcf7dbeb64f4339c63d3a437b5898be19f6ce62024cf9b9c89964569f176fb697430e553a7c0936056183223fdab2f910047ad5e64098a44a2edbfd3007b0b5e4a5d1e6ecb44f137dae2dfc45e96f03e75c900f3f84e2653efded35a3c8b27e310dc361c0740524e52a1bbecce57d59c4913313e62bbb63c95a93512bf09228918bbf921cd5c62b8914b7142d6abf8d632c3ac44ebb6936c638d56cfaa7cee463838a921398acbbcb44bce621bfd81fab34a8ec33810eeb89fbc3cc469990089d2291e1e873b31398f2799b8d62d429b998422ed634bd7a6de8e991ba8492c001fc5df8b0014fda377cbc5ac74e40d50773ab5c2b4d08dfbf3cca590a77f4db0380fe7af822207aaf99c38676327ccd9aad50b2d4db5aedf74b1cdc50c484d455429352ef0aacedcd9792dc26c66081c28ecabc445b6f1f547a24403e18b0468c8881bdc3e82f7bcce254944271c3ba06c80555c8f3d2d051fb6007507eadf8fb991f45c0c9e9ff08838a425a96d72fc20d642c2eef45b4fa43e7b380d8b6648695c0b9440cc66665435ffd3df10fd786f7638e13706f6c5651dfe5f125158ff3d1da84cad23129e11d79d0f95548318b1c794990174daa895e4b984c175136185be534ed6bff9231c215fbf6bd297e24f528cda523d62b44aec15fdfb36281d804625db07567fdb06779325987f69f16f19df737d5f65d1abadfae70a1a4daba5a87e4ea3a09751ece2ec21dd24f719b1f57e795819689c8f2e83beff593735825a1ff8e4e4df9d031dd66120dcba07e6bfbf1b0946b3585a5eb807c1632a75353e8f7b8c4f8ff0af978afe2bec80d3b94917773564d7efd92a79cad26360b599be49bc657b132b25f459d58166110fa626cf1731be419105b4bd235176d60efa939fdd8dc213c695674bca27f161da4514f646f33557aca06189698f2953674ee73be89e3fc4c014877c6bec370ca1fe446686200a94ded3382c4f4bc58cdc12c354a486463959cb91c2ea0ae965f912364c5d98acd40ee312178b479b540875fb2a0164b7134564bf7fabf59add993b08a904452152031a784cbd36e19a47d4c9371e7774d3433fecb5d072d059b01ebd3279ceeba80b356e3628874008d801ed74717c70a93411603f1faa3924414665a95c475ac42de8d616de8be5c00fb90e5ad13079e54d1c7000905b62742ed70555ec406b49cd4aa6ea68342aa7763530b180e4f790475eefe1094426b7de9e0163a4990ea3494909c6c6de6b7462d70c8f2dca3152d81c93a8c184b0c54da7fb604f835df34506731774e6b8f2361586ccc17f35c8e21795ccb68a5cd73355c98a17c9ae35ed22f6c0a36c4da30af96ce7347375144a80dd851fda4971f20e9d6d18878d74803b577af4fa8f34c05b380acbc5282eb63f9345e4dc1f9f0cf8808a204ec789ed31ac9f009790d5c9b7d744ee3b29d911014c12b53ff691fce0ae5d53dfe1c7a367e694fcd2f688d46758ec308f3f9736701dd825153df883c0dc539c9dc3dc7dc9a9a35f453c306fc57faf76451bef45889e4ab0a4a6dbd377996c7cf80e0e7192234475d93f3f813197ea2d3fb112c2e97cceef2000000000000000000000000000000000000000000000003080b1319ff", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 18, - "comment": "signature with non-zero padding in hints", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "0d0d1a7af2d4eff6d4af7435a634d28ec5d23595fe7a72cf76d30f1fe16620c64862e4aad54fb78f8ea752b1e43e4e5884d7226840beb36a76f6a9b1b7d50b0faf7b8463f57c66240e06a22f5f3de4fe35c1bc6b5e42ecb1c0758069223e02f42efdbbbfbc87b4c0736141a70e6dee41bed27fcfdcb94f4213a0f99a02beba309a93d343cc932a6fd67fb90d6de7a81101a678e6d47d8b1c8bd67fe386dca360be789555196e2ff8704c175ab60a8bf3c9f3bbae1ee5a128f67467d21fe8a62e5f8ad8127b8d7eb37e43abc963521e79d0f1ed57fa341f743246fe69d97afc9a13824c79f7f3dedd286f3de739158a0900c99d9c8e5603df109c25d993f634582c832a79c7bd8cbf3ba07fc4d9e9ca8c1157434515538285417e6424209173c6dafe54c37e4424de0f25454b1713fdc3e72d01a2acbeab4d7f60d17dcd073c60b0ad5252cfa137c138448c931498f61fdf8f449225b07e7e0fafafb1f274fe5cbaaa136e62362877f643c7c94946075e8928ec47c04ae54d2085f7f2b1ef0e46dfb31b9a19135b6cc9da876dace6f61c2766b463b24c0aac5068714e348dea399986c4e8b8bdb16768e7ab81e9ea13e435f97e35d268bb679071d5b99d0d2f1526833e8624b6e4ff1ba3f5af2b23bce93dc7c2c4370cfbe698a3297005c9fde7af66bce7c9ef68337b04d7681e303a824e00acdae2ee3eb8c3e7507e46d67a4cfcfa9473bfa6334f2170911bf2ea75a3618cac939d11d6a778101e033cad958aecd89feabfa19dc6dc73584917834ed6552966f7bec4546ab24c643db25722b3ba412de04e9195898388d9ce04cdd9343da69ac9b3d3155620dde4052e9e30529904f25dd6233bafd4493b66844c8fa5d831377dc3ff8829114000799801d46586dc2d2059f6bcaa43b899e089b4f3a5ed4e6a7f1df5b8d42fda456a70e10b2ae14630f27e4c7257f5df23ad032c1edde44073585c04c1231e085591771cb64aaf62febedb33df56bc62f4d126cf8be4332ce4965e6e67d0be7871d81dab963c576ad7123bbff510f282bf66c0c1ea04aaa05a7a4d410d0e7b6ed22025dcb6ceac78f377306e973973adcee776ecacaa560dc8008799b306d5e617b2f51159b1e5fe5daf40f8f488f077cc55bbefbe8f5a61c28ae2b1493272dc6a4e34854f73f74c3442d9c302f96b6e721e2956ee0bcdb9999ff36d74b8d4ef036afbdaea5f977da2b94d0aa9136abd6dc26348873090cfe3d4bdda4d962f9382576bbccf8ba227af4ca8e017f65b469d2e3d35132fac40cdf03bf8f6beee66fe9214e1bf684e0aae75e4141d9daa1c77ef409f56424b01acc7ffda11cb9bf64a9aa71b484b49b9ee82dd8178dd4adc91d8d176f83d2cc7516d2195917fc246ebdc0dba4cb5a54ac6169bacbcd79adb72d593fcc3fa289f1e4bffb4612ba7a3318e607b0b27733cc70a2e2b4099056731ecda3212d1719a6902cdd6a05bd70d389da1dd0d0b4f6c4968676fe33c6e32d791c85b16cc9f4289bdd09acadd9f902d9a91f1559bd40eb6b73da7a623048140f73454e4ccb4ad65038109f6eba9fa01b0a3fe1af228e2c4134be136db2b029879e101aa8ab264e554818450734eb5a900497d906e20d36eb3848b092c778054c5ecee767c00185ddea39160e4513be858bfe5c7c7febf97ee8e2b2fb477bfb10c11f3b756c0da1d87e3121ab4454016b36fcd8f6d2633c73d4528221974b3f21ed3d464d47bacaadbb4647320bf0bcde38b0a75b6c3aac8b72d3c2c179417d05858ae4bd72d9c16713f7c116dda3ff8164710d4d14964b33b00b268007f8cde2eacea5108fed77d7bff70273f351b4e160d28d02576dd5f3fc3ab264c5927cddb6f9a81b852d24842bd5db5c5f2d893b2f013fc75426ef2414bad1b845ba7833c88a8ce76fe2644455be2ac1b9d1e31791693fd65f1ce35fee9d17b42b444bf1277f2646a19d76952b3fa3846c3d258f9a1835a709fc21472b0f7de7a729111e850f27f88764b3ab4baaeb6cfc644b9b6a552a61a7286b5af8011ede05845cb9359232f02ad8b3605b00cbbd83069f26b610378055c004a456c7c44606125b7b076b3f955117e03eaa514da82a9650e8b9247902c5048ff776ecaaa5ea57df61d726ff1754d4b1393933599edc49617836ecf78cc7dd45750b666b73150496e3999e339243f5644d5a3e57c6cdef2ea6c967f8bc93c27aa56ba5352666ab6dbccec415f610bcc76879793935df8e594f5c6b80dc0adcea1a1d5854f447604c54dad61cf0ac91d27ef963e6889075163e89cdec0aebf32080efcc58280b705a029511f21d311c1644623f82039e096f7e1d2518928847abd479840b65cf10d15851976e47444d64c6d4425310a3b5efe9b584ce7aa01b1f79d6e3092486f91fe75288736e852c0132561a7616f21b7713ec53f0dc53432f53eb4ad778dbe14664b55553ba342eaf94e9f76320f8f658b4c5173ab938fbbfe20c9987318c1a5104efe41419926218d30b0c97a366e60f6d1240e7f601a1b119df36cda11bdf7fb531a27979c9823efd2a75c70387f0296dc7382f570fe59568afb406a48e7c13bcb40204c92cfe13b3980410b229767a5412a7db82845da135cb6d5b2f9f5b22518b2115dfb02115fa1c4c3177a55f5c194450f0f0a518df7755b0b12eb412f5f6ee2256bb95d2985bdf1257769718de9b4f4281c3eb3407f175c0b43fee6b94b00875dca0983ae763624bc4e84e9a78f778dedef5eb078ee87a34941005c15cf42ee05cafe098005b1770ccce4e59d9d3f6eab9fb2673766d9b70ac11cd6d8b9d00809e58a046d95ff62e78a8e5525af54094c907019ec661600ec2c4ce5337371a1daad0e37f3a5cdd96a3d985456a588b5c1f61f36a33c6444c3b67c445bf95e9035cd4f77191a95a7e4c20715e55dbe43196809123499148a930321e7b2cc7809cf517fc4b2b0b49e57cde4b6aae620fe8cd0b38358685ab80061c1c126a1f3a96ab34fa957236cc6c59ed962b3bb006a1c122da796bf6bcf7dbeb64f4339c63d3a437b5898be19f6ce62024cf9b9c89964569f176fb697430e553a7c0936056183223fdab2f910047ad5e64098a44a2edbfd3007b0b5e4a5d1e6ecb44f137dae2dfc45e96f03e75c900f3f84e2653efded35a3c8b27e310dc361c0740524e52a1bbecce57d59c4913313e62bbb63c95a93512bf09228918bbf921cd5c62b8914b7142d6abf8d632c3ac44ebb6936c638d56cfaa7cee463838a921398acbbcb44bce621bfd81fab34a8ec33810eeb89fbc3cc469990089d2291e1e873b31398f2799b8d62d429b998422ed634bd7a6de8e991ba8492c001fc5df8b0014fda377cbc5ac74e40d50773ab5c2b4d08dfbf3cca590a77f4db0380fe7af822207aaf99c38676327ccd9aad50b2d4db5aedf74b1cdc50c484d455429352ef0aacedcd9792dc26c66081c28ecabc445b6f1f547a24403e18b0468c8881bdc3e82f7bcce254944271c3ba06c80555c8f3d2d051fb6007507eadf8fb991f45c0c9e9ff08838a425a96d72fc20d642c2eef45b4fa43e7b380d8b6648695c0b9440cc66665435ffd3df10fd786f7638e13706f6c5651dfe5f125158ff3d1da84cad23129e11d79d0f95548318b1c794990174daa895e4b984c175136185be534ed6bff9231c215fbf6bd297e24f528cda523d62b44aec15fdfb36281d804625db07567fdb06779325987f69f16f19df737d5f65d1abadfae70a1a4daba5a87e4ea3a09751ece2ec21dd24f719b1f57e795819689c8f2e83beff593735825a1ff8e4e4df9d031dd66120dcba07e6bfbf1b0946b3585a5eb807c1632a75353e8f7b8c4f8ff0af978afe2bec80d3b94917773564d7efd92a79cad26360b599be49bc657b132b25f459d58166110fa626cf1731be419105b4bd235176d60efa939fdd8dc213c695674bca27f161da4514f646f33557aca06189698f2953674ee73be89e3fc4c014877c6bec370ca1fe446686200a94ded3382c4f4bc58cdc12c354a486463959cb91c2ea0ae965f912364c5d98acd40ee312178b479b540875fb2a0164b7134564bf7fabf59add993b08a904452152031a784cbd36e19a47d4c9371e7774d3433fecb5d072d059b01ebd3279ceeba80b356e3628874008d801ed74717c70a93411603f1faa3924414665a95c475ac42de8d616de8be5c00fb90e5ad13079e54d1c7000905b62742ed70555ec406b49cd4aa6ea68342aa7763530b180e4f790475eefe1094426b7de9e0163a4990ea3494909c6c6de6b7462d70c8f2dca3152d81c93a8c184b0c54da7fb604f835df34506731774e6b8f2361586ccc17f35c8e21795ccb68a5cd73355c98a17c9ae35ed22f6c0a36c4da30af96ce7347375144a80dd851fda4971f20e9d6d18878d74803b577af4fa8f34c05b380acbc5282eb63f9345e4dc1f9f0cf8808a204ec789ed31ac9f009790d5c9b7d744ee3b29d911014c12b53ff691fce0ae5d53dfe1c7a367e694fcd2f688d46758ec308f3f9736701dd825153df883c0dc539c9dc3dc7dc9a9a35f453c306fc57faf76451bef45889e4ab0a4a6dbd377996c7cf80e0e7192234475d93f3f813197ea2d3fb112c2e97cceef22a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a03080b131920", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 19, - "comment": "signature with a repeated hint", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "0d0d1a7af2d4eff6d4af7435a634d28ec5d23595fe7a72cf76d30f1fe16620c64862e4aad54fb78f8ea752b1e43e4e5884d7226840beb36a76f6a9b1b7d50b0faf7b8463f57c66240e06a22f5f3de4fe35c1bc6b5e42ecb1c0758069223e02f42efdbbbfbc87b4c0736141a70e6dee41bed27fcfdcb94f4213a0f99a02beba309a93d343cc932a6fd67fb90d6de7a81101a678e6d47d8b1c8bd67fe386dca360be789555196e2ff8704c175ab60a8bf3c9f3bbae1ee5a128f67467d21fe8a62e5f8ad8127b8d7eb37e43abc963521e79d0f1ed57fa341f743246fe69d97afc9a13824c79f7f3dedd286f3de739158a0900c99d9c8e5603df109c25d993f634582c832a79c7bd8cbf3ba07fc4d9e9ca8c1157434515538285417e6424209173c6dafe54c37e4424de0f25454b1713fdc3e72d01a2acbeab4d7f60d17dcd073c60b0ad5252cfa137c138448c931498f61fdf8f449225b07e7e0fafafb1f274fe5cbaaa136e62362877f643c7c94946075e8928ec47c04ae54d2085f7f2b1ef0e46dfb31b9a19135b6cc9da876dace6f61c2766b463b24c0aac5068714e348dea399986c4e8b8bdb16768e7ab81e9ea13e435f97e35d268bb679071d5b99d0d2f1526833e8624b6e4ff1ba3f5af2b23bce93dc7c2c4370cfbe698a3297005c9fde7af66bce7c9ef68337b04d7681e303a824e00acdae2ee3eb8c3e7507e46d67a4cfcfa9473bfa6334f2170911bf2ea75a3618cac939d11d6a778101e033cad958aecd89feabfa19dc6dc73584917834ed6552966f7bec4546ab24c643db25722b3ba412de04e9195898388d9ce04cdd9343da69ac9b3d3155620dde4052e9e30529904f25dd6233bafd4493b66844c8fa5d831377dc3ff8829114000799801d46586dc2d2059f6bcaa43b899e089b4f3a5ed4e6a7f1df5b8d42fda456a70e10b2ae14630f27e4c7257f5df23ad032c1edde44073585c04c1231e085591771cb64aaf62febedb33df56bc62f4d126cf8be4332ce4965e6e67d0be7871d81dab963c576ad7123bbff510f282bf66c0c1ea04aaa05a7a4d410d0e7b6ed22025dcb6ceac78f377306e973973adcee776ecacaa560dc8008799b306d5e617b2f51159b1e5fe5daf40f8f488f077cc55bbefbe8f5a61c28ae2b1493272dc6a4e34854f73f74c3442d9c302f96b6e721e2956ee0bcdb9999ff36d74b8d4ef036afbdaea5f977da2b94d0aa9136abd6dc26348873090cfe3d4bdda4d962f9382576bbccf8ba227af4ca8e017f65b469d2e3d35132fac40cdf03bf8f6beee66fe9214e1bf684e0aae75e4141d9daa1c77ef409f56424b01acc7ffda11cb9bf64a9aa71b484b49b9ee82dd8178dd4adc91d8d176f83d2cc7516d2195917fc246ebdc0dba4cb5a54ac6169bacbcd79adb72d593fcc3fa289f1e4bffb4612ba7a3318e607b0b27733cc70a2e2b4099056731ecda3212d1719a6902cdd6a05bd70d389da1dd0d0b4f6c4968676fe33c6e32d791c85b16cc9f4289bdd09acadd9f902d9a91f1559bd40eb6b73da7a623048140f73454e4ccb4ad65038109f6eba9fa01b0a3fe1af228e2c4134be136db2b029879e101aa8ab264e554818450734eb5a900497d906e20d36eb3848b092c778054c5ecee767c00185ddea39160e4513be858bfe5c7c7febf97ee8e2b2fb477bfb10c11f3b756c0da1d87e3121ab4454016b36fcd8f6d2633c73d4528221974b3f21ed3d464d47bacaadbb4647320bf0bcde38b0a75b6c3aac8b72d3c2c179417d05858ae4bd72d9c16713f7c116dda3ff8164710d4d14964b33b00b268007f8cde2eacea5108fed77d7bff70273f351b4e160d28d02576dd5f3fc3ab264c5927cddb6f9a81b852d24842bd5db5c5f2d893b2f013fc75426ef2414bad1b845ba7833c88a8ce76fe2644455be2ac1b9d1e31791693fd65f1ce35fee9d17b42b444bf1277f2646a19d76952b3fa3846c3d258f9a1835a709fc21472b0f7de7a729111e850f27f88764b3ab4baaeb6cfc644b9b6a552a61a7286b5af8011ede05845cb9359232f02ad8b3605b00cbbd83069f26b610378055c004a456c7c44606125b7b076b3f955117e03eaa514da82a9650e8b9247902c5048ff776ecaaa5ea57df61d726ff1754d4b1393933599edc49617836ecf78cc7dd45750b666b73150496e3999e339243f5644d5a3e57c6cdef2ea6c967f8bc93c27aa56ba5352666ab6dbccec415f610bcc76879793935df8e594f5c6b80dc0adcea1a1d5854f447604c54dad61cf0ac91d27ef963e6889075163e89cdec0aebf32080efcc58280b705a029511f21d311c1644623f82039e096f7e1d2518928847abd479840b65cf10d15851976e47444d64c6d4425310a3b5efe9b584ce7aa01b1f79d6e3092486f91fe75288736e852c0132561a7616f21b7713ec53f0dc53432f53eb4ad778dbe14664b55553ba342eaf94e9f76320f8f658b4c5173ab938fbbfe20c9987318c1a5104efe41419926218d30b0c97a366e60f6d1240e7f601a1b119df36cda11bdf7fb531a27979c9823efd2a75c70387f0296dc7382f570fe59568afb406a48e7c13bcb40204c92cfe13b3980410b229767a5412a7db82845da135cb6d5b2f9f5b22518b2115dfb02115fa1c4c3177a55f5c194450f0f0a518df7755b0b12eb412f5f6ee2256bb95d2985bdf1257769718de9b4f4281c3eb3407f175c0b43fee6b94b00875dca0983ae763624bc4e84e9a78f778dedef5eb078ee87a34941005c15cf42ee05cafe098005b1770ccce4e59d9d3f6eab9fb2673766d9b70ac11cd6d8b9d00809e58a046d95ff62e78a8e5525af54094c907019ec661600ec2c4ce5337371a1daad0e37f3a5cdd96a3d985456a588b5c1f61f36a33c6444c3b67c445bf95e9035cd4f77191a95a7e4c20715e55dbe43196809123499148a930321e7b2cc7809cf517fc4b2b0b49e57cde4b6aae620fe8cd0b38358685ab80061c1c126a1f3a96ab34fa957236cc6c59ed962b3bb006a1c122da796bf6bcf7dbeb64f4339c63d3a437b5898be19f6ce62024cf9b9c89964569f176fb697430e553a7c0936056183223fdab2f910047ad5e64098a44a2edbfd3007b0b5e4a5d1e6ecb44f137dae2dfc45e96f03e75c900f3f84e2653efded35a3c8b27e310dc361c0740524e52a1bbecce57d59c4913313e62bbb63c95a93512bf09228918bbf921cd5c62b8914b7142d6abf8d632c3ac44ebb6936c638d56cfaa7cee463838a921398acbbcb44bce621bfd81fab34a8ec33810eeb89fbc3cc469990089d2291e1e873b31398f2799b8d62d429b998422ed634bd7a6de8e991ba8492c001fc5df8b0014fda377cbc5ac74e40d50773ab5c2b4d08dfbf3cca590a77f4db0380fe7af822207aaf99c38676327ccd9aad50b2d4db5aedf74b1cdc50c484d455429352ef0aacedcd9792dc26c66081c28ecabc445b6f1f547a24403e18b0468c8881bdc3e82f7bcce254944271c3ba06c80555c8f3d2d051fb6007507eadf8fb991f45c0c9e9ff08838a425a96d72fc20d642c2eef45b4fa43e7b380d8b6648695c0b9440cc66665435ffd3df10fd786f7638e13706f6c5651dfe5f125158ff3d1da84cad23129e11d79d0f95548318b1c794990174daa895e4b984c175136185be534ed6bff9231c215fbf6bd297e24f528cda523d62b44aec15fdfb36281d804625db07567fdb06779325987f69f16f19df737d5f65d1abadfae70a1a4daba5a87e4ea3a09751ece2ec21dd24f719b1f57e795819689c8f2e83beff593735825a1ff8e4e4df9d031dd66120dcba07e6bfbf1b0946b3585a5eb807c1632a75353e8f7b8c4f8ff0af978afe2bec80d3b94917773564d7efd92a79cad26360b599be49bc657b132b25f459d58166110fa626cf1731be419105b4bd235176d60efa939fdd8dc213c695674bca27f161da4514f646f33557aca06189698f2953674ee73be89e3fc4c014877c6bec370ca1fe446686200a94ded3382c4f4bc58cdc12c354a486463959cb91c2ea0ae965f912364c5d98acd40ee312178b479b540875fb2a0164b7134564bf7fabf59add993b08a904452152031a784cbd36e19a47d4c9371e7774d3433fecb5d072d059b01ebd3279ceeba80b356e3628874008d801ed74717c70a93411603f1faa3924414665a95c475ac42de8d616de8be5c00fb90e5ad13079e54d1c7000905b62742ed70555ec406b49cd4aa6ea68342aa7763530b180e4f790475eefe1094426b7de9e0163a4990ea3494909c6c6de6b7462d70c8f2dca3152d81c93a8c184b0c54da7fb604f835df34506731774e6b8f2361586ccc17f35c8e21795ccb68a5cd73355c98a17c9ae35ed22f6c0a36c4da30af96ce7347375144a80dd851fda4971f20e9d6d18878d74803b577af4fa8f34c05b380acbc5282eb63f9345e4dc1f9f0cf8808a204ec789ed31ac9f009790d5c9b7d744ee3b29d911014c12b53ff691fce0ae5d53dfe1c7a367e694fcd2f688d46758ec308f3f9736701dd825153df883c0dc539c9dc3dc7dc9a9a35f453c306fc57faf76451bef45889e4ab0a4a4a6dbd377996c7cf80e0e7192234475d93f3f813197ea2d3fb112c2e97cceef20000000000000000000000000000000000000000000004090c141a21", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 20, - "comment": "signature with omega+1 hints (causing a buffer overflow)", - "msg": "c806000000000000000000000000000000000000000000000000000000000000", - "sig": "cbb10acfc660a8f47b48c09a8ad95ebdf7d5699a417096887ddd70508e82d3a49a69ee8c0a2aaa6d89ac126675f6c955ba4b8f234ffbd6fc0bdfa6bb95cafceb72c1b047fbedbbb192a571cac9398e9c19909852709697bc3def2d3583aa7874d032d6b1d36d681535833ce378a7be08b43998c887cbde0b6a8ab0948a5506d59f604ec85ae84bf72eb1d36769c5f2eca3b38ea6917edd02d28840f0cab3f110b027cd877f92e59b0328163587e4606707b39f16e5140a7156193ead8076d084aeec93268cef5b9ee0756e0069d0e9fadad1b1ef71bb49ecd95da70d3411ab40931c0c30a2c4a3a8d87de2040ac64df2202b2533c4be396f9e0e9d383f3573982cf7e05b67cf6f53d15454f48aa1825b22ad9dc9ef1ce6db827bd0059295c2409d1e5b75fe6387c795bfe22f6528825570dfd8d58fdd90e609e59de312e7ad90e1dfb1b302c90d1c71c4a5b5c0034a0c8b8a18de6fee029ccba1bffbebdf3ff82d99ccc329982a8f04f0cf7857c0826a6c7a9505da3c705f7c8913ffb099269d8e3eb679685f22450fcc969de7e743af0280d40c2861743d56bb92c992b566df7a29c375d836b38a8a6e3f89102735e51f4c65861bde29b6d692375e9e5344ec26d32ab5d1247225e7ffefc6226093289d0c6a8655d9ed7eb5a845bc6b4782d4cec07961ced24be1b829f57a05eb93b18adb5a18aa5d72cecd2c6592614868a845b6cbff9b876e544c5208b3097efadd383ce2ad971c252d67c6a9f2ed3faffbf845164de52bd195c2b2d3df673cf6d9b2690aa7e4050cfe404da6faec1fafaeb4b9064169af0d46bb30b55c80b655f0d6472ded24c802af74d014a14dad2fd88941747ee0097de87d85191584d8c4b051aec8653373ae2a1c2cc16c354a709118633f1367838e491b11213531bb0c3bf6170825cdd94d44ef09de2bfba62c7373b479d64bb45141e130c9de3b0f794b40bdf3bdc0f6fbfa17cecf021586a914422e83f06debd5d02ad2bd64263abe226d43c247f42f36d2d47ed550dca03ab844048a0c96e725c249527c60b866063b9b6b4a1a51f7ced09ca394dd01b784a30ec3477bdadfea46f34d376603c4da1f07a80bac5ae436baab3592ea9f9f3b6bcefa27dab57584505dc661c24a89612d29012d3dc9432191eabe5a30ebfab94ed93fef419759ef42462edd662d3c8137d13c530b489340892a4cec72783f0c7c788a24d43c331b3a63d75951e4fd84ac251df2dd183569fc031498c0ee826debbec605ec230fc1e49eab7ebeea6767181cc3b47f1dc7dddd058c51ffe0f87e6648a5bdbca0c0686daf6bafe5d158eb7de470adf4228c24ea70d8946573117bc19c8f25f851edbdf4fb1d69500501f9ec5f1c488c781ca8041a8767dfd9275b8dda148c468104b8ac60fffae510b4b0d31c9699d8d58eb441b3d6702d153b0702d81b41cdcc1e8943d0d5147c737e85af4f014bfb2908488372ba716129d63aa66ac8c02f91d48603763fb05053abb58e299d1cc9f01bfa7222c4bb37f6c69ac41743763a0b1b416227dad58f6f292ad13b7b42987f1d95921f997bd3aabc6158fecffdb3ec953b77f37effbc754cd16c22915dea3b800692e7975d4fcfec46c4e213e53128876495bdd1e5fa1a55e21a31d9704c9b08a43fec1193bc8ad23d3047060eacb17ea591a49aba6535c1caac0bb98d73ac36d19d84e6e42a8e85601f6376d1c7e65eb0505d7948b439fe34f4abb99c4e759427bcd100521263c181297c131f22d948555ebb2b229c81e7a00bcdc3633fb9d4e7b478f92f369e3a3a9db10cbc76be2e7a2932aa610002f128145ccb01716f1aaf5bf0959c4dab108353185dfc4e77d4aaf3f4e0c69caa0a1de7a2ca9edcbaf390861c486992c3bb02aa1c9b5c6a6a22c4e49f50d5e771adab52d693e8c2bf9af298ebf64400ab408c365f1a5beda25f8e1d2d6b708c63f5f1f667061ffb735960016dc393dbe7fec2a7b46dc4911bd46b06e222f530bf997b1e31db8aacd7f80a267549c6ae8b600eee5fbbe2c764634dba1d473ce148af811a7ef2b2a42b975ff5de88819230a59b5d903296597cea937affbf552b80f845c2a388a08bd4a4002efbf48ff70dca76c101d0b74b95b758b9521d98b8974f889eec2c3d79d9ccf6ca262f736de6e3ca93a551b8d2c5fb8b73e944bd05e62503cbe7cda823547d7446a8a4616becefbc8e558a4de3d62ba91486bf4033d4491642790be60ddca75eb5a68fb36b0c6ad4e70364b077ab8fe7b305caf7c70061aa8b466020845363257badc2da8861cccc504aa0bee7c48f9ba403350d4d46529b08e41d30af6f69b7fdb6fbec8ab6ea3e4eb0dd8c7e3a77de8ab47610e7ebebd9f5015bc7b7876c5fa0b891a0fe4015827012f10260943c08f389aa67891f0af67d5e71742bd852dd1160a9df66da04827cbdf3de6a1eb8e4e24bd2b1dc680a1073807795a2e9ebea30cee0bf6479494b7f5211e233f2844a663a00155ed9482943132d9fa0c966cda5f1f64eb96e456053342027d14eb3c70062c0db2094d693fec31d06241d886b9dd9ff13584a47a7b843757a75a6e28aab82caeb3ef256c70a17a6180dd890a8e6f4c6b96711daf9f799b113d87f6bcbd56baee9dda09f6f67fc1b1e1e64fcba8497b20339540cbf7ced0e21a554c35e257ab64cf4761d12dfb457dd9bf2f5ae9701d87c8d5c367b047f378556708645684ef9e58eadb8ee3e4b97a86292bd9ad8acef3a3a9aaf0f2039be4640a953b2cd8b19fd5d469cc1328443c4c0ac481f98997f359fd561e11ed2f03f123302c8ef74c60839025e11997f82988dc3448ece0640473a1738551a4f7e68afc84c45cd92583950da4a8b5a043fac1dfb1343b0a1f706a1e5e8492467bbd1924fc3d430978bea871ef59062cd29e2ad44becc9caad78b5dc3c49e38b8b26de0d957e8e73699e5d2f5281108aa37f03b12d5bd50d904f0caf4f4dcc74adcac837ee04dd21f199fc42ab39fe6229002ac48dc4a60fc35eaa653c30bd275b4ab7d32a5e4d09533e7a3dc0e826d8c812ebadde3ec7eb3987c17ef2fb00fc1b6ac82d650f56646e9a11ab2e097e0697954f252a7a9a390559b79ec5d38da9e5b0b6f027c158643837a1d4ec93b50ba3de8296e022463c6424ab47561950e8122637dc682ddabc523780323049b1ff5949394844856b95e06307ef3362b8481ac2ede882a2e91299433d18513038cf205ffe1687e8fb011dd40864b602602fcb8391d81e05f6bfe5f09bc5055b2696f32a771321b30cb79fd0b66a2cb0a5208c4797eefbd81e27a67a6a0bb39c309a71557c78441d76b3fe7ac00956c184e9646984ffb2751f61f72382842ad62a032b8de6e2317cc2f2d193ef498a133badef5b1869d85edd1f94a4f458cf21f0b80c3f2ecde7ca19a0fc7c7f7a8986bd023a02a61ec667c0c709b1f89ea5ec07785d72a1f2169a1b5b1522d8292ef30a677662080c91fa774f28ee40aaee0f8afea96bc7d858eef054b93f3deb604c5f9929b1a5092f68a67462ae7fc60c11cf29ca950df68d4060edae6fe254160525fe2466a9b97144e8401b230560ff5b3ae53322905c8d7794d2d4d63ce55eca3c1ca0dc97df11fff1adae8d065e3943bc8b1a20ed1493569c8f730b1adf11001a3cc9cf23d5919a4725069fc58eb1f46415a57f668a2d5a584ee41dcf1423869922f78e7292a846c3bc2fb81ce36da0526967590aa548a5a291f5eb69e67391b0e257bed22095999a70b2d8c6d39f23551bb25c94584da70150dd01e1d3d5bf26809059d713368f7ff0fc3c8657c3c98871b27ef04a958e8d8ce255d831c28e8d7a72b74adb806df346cd6342ac6b4de114c08acf7b9167505aab8d6b5742c0539252ffc531046998990c727f9d914f9426bb024af1e32bac4ba5d1072e50adfdb49feaf9472f82f74459a660963e857ca46db64d945d19d6a3f667dbcb253c28ff5e79ad9ac6c9e11012db47663bf69e1be7e1f829920144d0e8bebf9557333bf94d8707b98165a2fcc7dce2460c5bb5966d57e535b234536c430b540c32bc6473f7b5994d4cc40633fe5f3ca0e6ac7d1e65c55bc15bbf643a97a346e6abb500e439a014af2592298572cd408c14050656933d4b9c74d45864ad3d48bfd0c7be151c82dd7543690e09a4c450059d703461192ee3e9823dfc6a047493302256df5e5f59b820614547ea328e78250730ea608191685ae747d323a9c60b2c470a724d1fea2f789263a8683873bb81ee692fd1c26110118bcb69cb7880437f251fa8338e4378e34434edce0defb0f0049b44572402e71dad5f56b63f774aa435ef79883339fbcdf52bb6a9463f4fefdb94d3e151552792403f6997c160727023a9ded4bb38dd34b4a54a373ca403720be4703d9fc3d1fb1b7883f58cf0d875871e6be474631ccf3e209d3d4beb5a6ae2815559b706bf583fec48ee1c0e95e66054bd7ac2479d1d773dc4e36e526ed70ebb02e74d1726fc9b5167c4496eddb822edef41994e84ae1172c1abe3b31c800c1baa04c71b4074634be600166026e1bedb081d3a632641a9e77766e579c3236741b3d4448576498c6c8f20439657eed16767a8b8d929ba3abb9c3d0181e2e3d4e606a7ba0050d1f262e67a7d0e4181f85a0b5b7bfc3c7e4fcfd080d19222b38", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 21, - "comment": "signature that takes 1 iteration(s)", - "msg": "0700000000000000000000000000000000000000000000000000000000000000", - "sig": "424ac14fd2cf3f7eb28b104a7418909e84eff42d2f6e7c4ed3874838f8580d918a5d229f8ad72a0e093959da15f05e9942fad12ac1fe73c9de377b85a0f9d7203e6f8d3d4e83e5ac52a82b7a77c0096d92d40f2c1b7e194673faeaf16d7bf11342956d14d7bcd45f98ac9003ec86da5a1b2775d0723ba7350b81ecabc464be480d834b3965fd6554d340b9a11add210c6228f29a8932b8b6a00263777039533e1580faca62a7885372fe15b4e441a7595a13966fc05a95926fec9eed7563b1347d2b8d55e15212148e9f7e6e6b3e8dc30c6a1d213f66f574588ddf5d559438b1bfe01e851b15108baa97b64273d2e850b8ad504d2defb158e1ef3d4af5e1cbebfdf8a0e8037ba4def90bfdde7f2eadb3da96becd9e6a95e286e120871217aca6a8756f3ed7a11c2f75e1a82f9ab0234b1cc2c8178ad690e8c2798f1eb8b83178f39d7fdd09f44d7df268e7e062566a4516b1a1ceb97049df4646e8156e678c5f1fe2705b0c261db71a9932b8f41950e326a2200908c4c0bf3681384ae1501f5ddef8ab98133519452c725eb84f36814577108508809015af4d8758c23afea3815a09537477e8f6c7694a81c1d08c822843b9e67d95592eff819f6c2927e403f9962f36364ec2dbfe494049884d61695331e32abe6272d5a44961b8679879a67b142aa40729630d8d24bc69caf17774c6e2b3021b9181a8a498586a0f7d4109c5c82841454785873670dd2f60a4c278a373986333120c1b17b4297620bf72c7fc126205c1b240c6d60399b715579adfd96492e350a4145ede8d075ae544d051f58bb9991575a6ddab224c9c83a39b6fa9b49444fb0d2b8e32464c216e42d02091ff25122f85f9454f6d818034a30e6252cb0d25b572de3ab1c669709e04fbdaeffa26d0fc67d250da0864c71d74f8c08b5ad15cb95a33ca5b03d9573e83b35cc173afd97e88b9ea859861384cf8ee6338bbe5768cdf9c84cabdb8b332aaa7574ba200d496aa1d6be562f59be022d7d9cc63fe6a35100b664694b5bd1f5a610cc3d7a670f45b47befb8cf705339a8a5adec9fbb9f1fc4196fd3ad2a5ec9f3c9bd48e96bd6ac7276bb00705aee192106388f2fef2cd3c7cf00a159459314260dc49d9630d9bdfd0245db95fff41703f3236ed1bce77582dd6de015ed6d8dec0f2f2952fafc0e11479487a21c1cd61f1a9410dc730dfdf01527c6ae4072eb1591fb5f9b6117dabd9458331d9fdf582acde4b9001c6b6c6e048120cf15534db40e7b8f77fdff60b08a0ed6a802095fb76c71062dc34a612fe34f6598529c2028487457530c154d18709381cdb36b4ec697a2b921ec9056c86c5e73dd74b63f1844b1240c703c6f6373018c2daebb7beb55ec0365c76725063a3fd212ba80bc951baee1b58ceab532e58754ea44b0cf815a0624e2a0cf5dea9bfcae56b7ac74e4627a05bd8a2539ea4d25a3aceb003c8e7b750f0e8485eebc84b130a54ce8926b54cbb54b94db057f993ab426fe1a3be7a997782fab08cd704b1628b9d40af916730014d71d71d82bc09a7a17855c314b9febd079e371598103a4fc6923fa47a1979fea54c0bf7542a6e54d5cb92814c824d94753095d2fab232153f204d16aaa6acba4c72ae358eab79a8b51ef06db93cd5acb606ddf4dfbbc031f697486c284ef2627e3e65a5998f746d6ed934cedc1204c72694f6738ef0de7cf25bd147c938f3e7efd6def80c01b690ed200c21f56df02f7f31e90c0f05e61c60e2279b307664f491fac8f3315e48040ed63f6b68cd7821bd9447a8cd9d95aca3b16d721ef8e90d668636ebb4974553f41e7e9b075eee4e83e118fa74f2d7197fa135dc53146e7c194645e4f07412693320117cc3cdb1bca814e0e30fcf5590ce237e0479bf088cb0f68c2dc0b53203c7c007a4bc6361a32e3e153cbef1163eba0a3d7e5e133fb30c6f37b3f92e94abe270e7c3e8c97056bd12a1d588f919d65db51accf624e0a356d6e6e0da3c67dc298746a39b6313bb658e3451a2b1abf7efb6c1e63b83cfaeea9a17ac8f22587254227f5adb2f41f367bb9e4530c7fb93b78cbf60b7619a25f2f7a00aff9d935c294e82102eb0e96da7c3d4c87ccb896a5e5ee3ee13da3d94655a66c0c3d781a67c23bbd53cd7eea563a8d63100144ede22e3af96b69ca18d5d5be5849d27c1db28298d485e2fba3c7f68297c7f883049d73ffbb3a300c5aacc1d8a805205602e410e76fc48adb109cd47624c2822e6dcc0db0a28be5401a79659d19b8bbdf131ce04fd6278130aa2f203b9e0f52134a3dec5a97c4753da3127288ea0969fcee232837ea067e8a34b6dd4e1ecd7f37b8e956d137be78be955854a75d84a339f3e80bebe8d295ec1149bbaf115bfc84e8cce1cf994fe067dbcca2ce1c378180bbceda95444ae535a9ffe1819caac5cf95b86219e95c62581d1110daefeb4830043a7a9552de5a55f250e7f1aa5993f87647c92c27256753d6daf32da18c1cef9bd5ff5a7a8e182d071f1e75d10be89f02c861a0d05257c08c9e12f877a22c8382ec883c592a34722f1138a1e8b5ded41e970b97ba2a69c386f94b508b38a59b464dee983741e61d0096f499f3c552f43ca317ddf073e0450e800585053830681d4a8a8ecd5b86c901285c84278c06b86375a04fa7002b259cd61d5ecca426aa334659284945ea6c5adedb7d40835c6134271d641bdb19cc3617bfdd53618252b4a684a259b82982b0a13cc90ca931c4e90915d2d7a0abdee3f78764b41e3236e2ac21e138c0cbce20740cd17f34eea236720acff25161ecd4c903e33395f51d2c51583407b35a044d54caee2b66dcaba84359218c6803040b19a39c0e4ef570fad7330041e024cd194326891547985b10e505c6e6b1abdaf3fcd63c3f2f08b2d93aad41e83167d969e54b12745b328b5cfb93266afa793bf00c86270ab98e2ab44b2be16b5e522ca280cfb0a9a4f744900f0f44f6126b787274b2a36232c84b563dc3a5879c83c34cc6d644fedc3912b10e9806f944440b00883bb76d51782f928139117c7358cd38a460ff73af4d417278b7bd463da86ba11bc88cff14340a24f675905c7edacb121fd625187b90a3152115b3ce1f49432409fa629384509cf51426948c71e76da8efbde2eeb7d3f3e576f18d4fb61f90d99de2bfea2cec28468368610670890ef26e05bb108dde48095251574c20611ce68890144750c62a9792815a89ffc50ff0d76fa0f708d917f3bd9f840b11085445784d2017e54266c69f3fbef4c8fa82c0723ba58736aa8466a81b00d563dfa074a9a06016ffb04f029bc12c53585183f237d84c343a13b08b484e1625be1b0c661f697ad5097040fed2d3d46c6b1229157729b306694bcdfeb4eece5b5dfa8043a6fcd607e2f82aeda46e88f8d59f2032fa439365bfda8ac7b9e09ed8020c045757d510d5de5dd0b2520b0f74a99d8fe7b1915d82491a270d1a1c554d0c05d14a1419e71dbbe5df225fea5c49b73b84fbf079dbef25ae8861e58ab8bab6ec4ad07dc10072c5627029d4a74700193d12f439a5bdc41a284b92499b3ab0f3973529ea148053da54125c2969603fa55d3dc30170568ac9642aedcdc817b0f4b8d5d31925428afbedd21fc7f1132fc7e85284723b4f26ba1b50bd5fea2d81b12f4451f97331c6af0c82aa9d962ce034df061c32a1113990a9f320291993c9d614c42e2aadb5dc52c58daf8d22bb302e1e64b32e16394cc0c44cf93bcf811e7ad772754b6e9c2dda630449e005a0303996a69f5ad647f98908af4f857af804294d416db784c34d2d5aad7d840e135ecf6b636dd33f4ba29d0f12fe3967260013662d8bc23a34a0f8a5df93e111e8792140487eb04854bfd9bf679e1b38de028ea5fc457cbc8e2706fced55f5363425b0c2c13cbad1ef96d18f11b0fb3749a561504b8fee8cfb4ef9c948e3efaa2de6ca38fb445382af66855f3c0603ab175aca17e1b005deec73b03eb952cefcb3cd5860c40578e8a366da62a431916ee212d9e5740fbfc42f6d0e0951fd2f213a8f6f21984e01832c0dadf56b3de4833b849b7d0c9125d7b9ae5c6f245703d77c0298c9b6abd563529b3f2986ce54462f050d18dfc85a840b1633b2b0373e585f77c106d70ff711d03362af483f7812965405e586d6988318effc81e9fa918ab278e97e0d6d3932e24ac17ba537f568f8b16bdf3d45488cb34f696295f7321b63a76101ec283f0427a533544f752cc9d3c277c59997e01604192746353421884142fa23dcccb3acdac509a5688089ee919230a9e0ec2804254a153f544977a634bb13880f3241daab08d1b73bdd8fe4a187e9b4c3758eba88cdcd9fc104360b2512788f4d31a23c80b78c150af10e1a41dd279e895ae9e66ecaf2bf32786c11573a74cbbb93b82255f9ed190dafce6803f07271889828696f5f8173772a7142ab46899c609136713cf7a3f4c5e9718c84ee8bce8b4b5ba83a09e421c830eafda214c0e0b3dc28d0f1adde9b5fd9fee6a07a328807d0e983cef6383ab94c415dd1e649d9804f571581ae0c7ab2896e86a470a9eab94f2fe9e138e91ac103cd770d27af9648ef83b5254696d72d7174188bafb05114a788d9726c9d7eafb182348618cacbec6224186909c00000000000000000000000000000000000000070c12171f24", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 22, - "comment": "signature that takes 2 iteration(s)", - "msg": "0f00000000000000000000000000000000000000000000000000000000000000", - "sig": "46b40670bb3da2c35f9649c9cd3fe613e63335a645b948018b3cffc864412f8868192a9d81da08d1e768d0d33d4f7a609dae1e72d4408fe5f5660f7714d7d3725deabd87d32d66d041124a0921a71ea30d8758427cd8978c2014d83746c7c29ca7781125afa4ebe984a11da34692342493df2c8fbcb50c83e56c9afc3df2a5d317add757dfb4439841a8d91d596eefa656f1953e7fdfb63e29a23ca3825a1c04e09f766ca10aa6bd05b9dfd7910db1956f99326766839c4dc0f653f2dd5e3a508fe13c2f0624d3dd0c0f764c164d231cd1f73646e542d7bec86e7ea0336583e86c2811db5e28e18f34122e86a37e1de65f5d7836c35db6079bcddab304ab6cf752dac710004fc24729d760d3d9380270c5d1d777b67ac830dd52c3548bda02f0f7d0331aa6c8414fa7307237456105c3c5f8463aecbfbf4d8c7f7c3b06f940592f12928a7a018595c1972705f8798fc75e2833e95a163ad24f367cfe85545fd0e0992775be5c074ed111cbf001bd536d1ce4a0430d963728a2e25d71c3efe9c385a6841d7f4c6d293a64f83429f064f3584ae0983dfa4f90820dd229f900e41447c07db5dd2a61868438b8f4eabd475da53e8f1c7d1120e366d774bb95839f6b3ada1f704198e06b13760447768753fb449c0d53acc22845a0a4e5b047d008e08e2f65c577026863ed25e1dd7d39cd4f0a7d823f4250474866b80ae3a2d19838cf24a265bee177d20b9fe59f2015092b3362a415f05e91bdf13ccd1bf3fc901a63ef23ef74b41cd74606c687ed6fecc665ee4fdae3a305392f59f9ba7e6c4a890c56c3115a2cc760f3166ba1c4e534a69bbf738c764cb228204799afdedd6660fd4a6b7856a84e714e58247fa068f859796cc4271ae915e62d3ca3fb43bf884fb8cfc39ea89d3042e453953849efcad7852d67471d2004b4ba8937a5c508109a19519fffa989a39a6c68f1ce9268469af6baaa7e0a93362f5b87b0ca24d5151b99bdac16885d335d6bf11c2a574a734999815843121bec25ba9775593ef19f809be5b63f5fb01b29f8f0eee9f1a69f514c0f17e90d40ae9a97f6fbaf5804bd036b6ae7cbc161865580f763d9abea93625096f3730c77cd0242f387fca2fa573f2638887417bd80968e86594e1ff547ef5ef4b9b49b0524ccfdb3701a8de2f7ab2eccce22ba93bbafafcc1359c2e3652b67250ed313d6564ba245200c0107fe749c965ecaebe28c79f24955a436c41b6ebd7f321938f4dbef88e30a34e5b2a3763381d0af8bd0176feabe3d467eb985cf4ab28e465b7896b36d2aabfbbd26931fca9b76e2eb1befe51b45d640ba468488da4093fb2ec7c77ae43c785b6588ebfbf5568c1299eebf0046e28b5f1e897516edbbbe99843e551012daa0157e03d1d41daf987b73ddb361c064917b6b8b4b23c31dbfe01e56960e63cec546e5684b057ae5f904333dc33ae1b0018875cc13f39e11b247db82e43409ecf16051be7e8525c9a90b68cf491830d2c583db07a5bd95ad69af0e4327cdccb9339d96a4aa201ebb86edfbe7176cf63a409872f73107c3f4f068df79ef817efb2f0837e665c7f2fe0a56c4e392d63a1032eaee2894f3bae6df6a70a430b22e9be6e15bef3a9af5545332ea3a62c94d5a6aaa8870c303b3460b3be88fa848fb818a3e1771c329f676941a628acd948b260541ecd1701c6cab3311ed86eaf0950675808ffdadf0b97f98e9da2193258b74d589054014dabe4c501f2e0fd81fab9cba2f9c8f70be8175da44bfcf01ec6ca5ba7f1039b29e27e5bfd67970e5e561c693a1ec2023d53cb1ed32f3614cc132701dbea3ab4d99398f23eac52b3f5c5f46a110d77f0d9c660b432bc57cca8bd38b4b5dcfc619aae56d7cd686f3fd94fe419f8fc54c9ea6611b4f512504ce87216f768abafa48f3825b2f9afca3d419151d1637bda8aff5e2f9a7921421fdac429c66c6a01832c7041f74fc81c47e4172f9d95b200b1a84af4dd9b677670bbf356d590f2fc1aa70ec53ae94331b2ac0f1a8bbc7dd600cb06c76f2f340aa2c8ae102cf9c4ba7126414da52a1d8ce3504ee282a02a9564b149c041694313ea3f11d9e697ce692441b3baa25b308f42eb7f9d03ba3b5638fb96004fd0ef2de66c6a573ce2570e19e75d5c2bea7d5c656c2ad6990cd2d8feaa9eb025d80b6483e6612888ae3a66f646a61cc08534fea6f31447af5535308e81e3dbac05b488fa9dafbfb31b7fc1773fed73556e9caa5864b4871ae4d2d472385ff62a61113ed0f7584220aac571b69373f2618887392f88e4813822009fca474af81a342e1fc7be442079fe882e8bab95b147c1a196eb079c7ef718c194e5d6a5332a63f3f15cfa08453afe796dc433399c75d8e7ea603c17bf1a133fa1407dd76489c9950e501e64d09a7ce59f886b3b80af926443bd3b04e33e97adc795fb4b775c8d6507dfb7aa254d3b994e6412838a03209ed3ae2c15cbf67cf00793c7b7bd4d1e36b56aba5212c0e8c82752da39686254e5357d2eb0ad691be3feffb1b09620c2b0b2181e510b47ec2fc0257acc3b847b90c0704eaaf48742e5a50498fceaa8945180026647a7f474cada887dd657f4003080d5081c1d37d4c2c8a1ba5e8562319d741b01bec47cff4fe1625630051b12accb6c919171073ff9cdf1d138ded6ead47440bb2f99424218156fee650daff3c777168b43548da1b946bdd16dfdd099d83a7c427f97f83bab18acb2650846d39cb41e5283564232fe21394318a2340f3ed2c6c7782d27ebaa780ea81ebbd33841f834756b74d99de6a17280088ec6bdad04144794594ccca8feee1fa09903953df806291667b686c9d5f77d89700b0a29ac9c95ef647d0b4a6ee30b99bbc9392a4769f4197f4289892f926d744d8b62e067edb5af6a6590981261b7a9c3c9f2b69833251916e00ec5710514fdb29ba3c25285001ab2652de3982f7bd960b60ac2fe285525f588167305afd30f059ab723c1105e6c657b5dece838d79d4dbb2c14cc50d123166cc4a4f01d15d7f8d4ce10acef8ab06132cebbc4426762b6616ad9c8d700dc7c53a1bed753569b28f6fb38e2334e50efb6b7de233b93ac1e0b4a71c7cfbb7002d6bd2a7f91d22cd080c182b989c2045fa5719eed2aadb2b409a73ea00ca3e9ae74e7fe61b18e25a8abed293651352d50eb2a341ae24d4549c93102b5bf8d9523da6cb97d6f0fbf4b64d7b65e0ffbbdec1ac74ab2217c464936205760f4d46139bc9066fca14b65f004b9432c723c4091ee0e81f5549200aa99445635c910303e697e0a08847645a98c12aa9eb42fe38265b09fb020ee3f6fb23f2e501c3a8ce5fde7326d2e9aa2e20aa770d810c3c11d86a6ac0296b296f2a1215fd83cb369abffb3d783b9805b0f46d853c73c887038584a30a17c8bef62ed7170841c09416924f67198bb07749cbc12412185f1d5fc4021a504f1c417ed5965a864140364904d33451937d38e14e8452f7d414949e9932e552afe0b33ba1bc63baf2190d8575e90cfeea69f5d0a3182d726cec66595065cf9dc22657cceb7cbd3afec14c84e900071d9d08849bcb1e20ec70c1dd4046f914f80a41afdb3b435b75bc125cfa2e6896b288dfe947f8c3edb82113a6eb6c35bf450191ad5abc514d9eeb6ed6fe5123f7e5caea3de2f19116c85def416ef5dfb47ee08957fbd87920e9fdd418895459b74a2fc62ef11be0943cfa22fbf14cb859de45a4b60deafb70e072889344107d0fe924fc68aa9c13429350eef78caba5352566f8d80b64d016265e264a1b5f00064de79c539b0552dfd3880dd9f77903465c777cc78fd137f199030bfb292383be3caabc1b6bcfcd0dbf4b7ded13b93f91408751808216e55a2ec4d39051cff5784b0db9e4d3c38fb5093bd23b29d82cce55e77710bedea7d9f0ad6a47929faf26f8d50bb2b2f038aba8d970939f4e6fa02c3f6cecc76f3a4298f66a7976b475d787c3d2ed3496a4cd9c47f864451f140be914141546580364a64215504d36cffe6f61a08a4f1940d965f39cb442c6705e932bfdbc29b612a8abb3925c3d9bec1c9630f622b0ffc7d8ec2425022882dddfa46bee778fc94e304e9672cb9931cb4b75edb5514c2d930e0de245f15c4dd422c0fda02f6b104c0b37ea2df5c04f83d9a3f644930eb54e19b7a2a5356359d6370bd4635fc576918be8547b7aba9f11f1dbf10697c8794b06f7ca1316c0e9ece8e51aa3a6d0a77672292ea5fdd50b399175d452f18754e4f3ebc41325982e2ba3162974c30e19fd49bbacf10e3cd96254cb3f43d6ce1115650a0522ac1b14acae1a3231579589062bd63a55b1aad407c0500b420d0840e49e941a5fe6c6cc196ce45d0d16289199cf9a29130f6235a3bf9e8598e2b0213ce87fd676ab5b621a284567172fbe5fcaade672cd55d1f6a5535348472fc836be896c332919fba13652b941a35087b44deecb7121191c548e8a7161b561a6f8f7cb4beae6b7f3d194f420ae758d209abac2f36c144f067a829cbef57304ac7541f7089bbd97821312a4c074be9daf5a000137825e7a406ab564cc16fb7ecfab4babbf00b1f13f8e009481e88f55050d1d2e313e424b4f6687c7973350585b5c66f2fe698a8cc0c1021b53637dabaeb2c7e0f35154babec6f7fc00000000000000000000000c0d151a252c", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 23, - "comment": "signature that takes 3 iteration(s)", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "0d0d1a7af2d4eff6d4af7435a634d28ec5d23595fe7a72cf76d30f1fe16620c64862e4aad54fb78f8ea752b1e43e4e5884d7226840beb36a76f6a9b1b7d50b0faf7b8463f57c66240e06a22f5f3de4fe35c1bc6b5e42ecb1c0758069223e02f42efdbbbfbc87b4c0736141a70e6dee41bed27fcfdcb94f4213a0f99a02beba309a93d343cc932a6fd67fb90d6de7a81101a678e6d47d8b1c8bd67fe386dca360be789555196e2ff8704c175ab60a8bf3c9f3bbae1ee5a128f67467d21fe8a62e5f8ad8127b8d7eb37e43abc963521e79d0f1ed57fa341f743246fe69d97afc9a13824c79f7f3dedd286f3de739158a0900c99d9c8e5603df109c25d993f634582c832a79c7bd8cbf3ba07fc4d9e9ca8c1157434515538285417e6424209173c6dafe54c37e4424de0f25454b1713fdc3e72d01a2acbeab4d7f60d17dcd073c60b0ad5252cfa137c138448c931498f61fdf8f449225b07e7e0fafafb1f274fe5cbaaa136e62362877f643c7c94946075e8928ec47c04ae54d2085f7f2b1ef0e46dfb31b9a19135b6cc9da876dace6f61c2766b463b24c0aac5068714e348dea399986c4e8b8bdb16768e7ab81e9ea13e435f97e35d268bb679071d5b99d0d2f1526833e8624b6e4ff1ba3f5af2b23bce93dc7c2c4370cfbe698a3297005c9fde7af66bce7c9ef68337b04d7681e303a824e00acdae2ee3eb8c3e7507e46d67a4cfcfa9473bfa6334f2170911bf2ea75a3618cac939d11d6a778101e033cad958aecd89feabfa19dc6dc73584917834ed6552966f7bec4546ab24c643db25722b3ba412de04e9195898388d9ce04cdd9343da69ac9b3d3155620dde4052e9e30529904f25dd6233bafd4493b66844c8fa5d831377dc3ff8829114000799801d46586dc2d2059f6bcaa43b899e089b4f3a5ed4e6a7f1df5b8d42fda456a70e10b2ae14630f27e4c7257f5df23ad032c1edde44073585c04c1231e085591771cb64aaf62febedb33df56bc62f4d126cf8be4332ce4965e6e67d0be7871d81dab963c576ad7123bbff510f282bf66c0c1ea04aaa05a7a4d410d0e7b6ed22025dcb6ceac78f377306e973973adcee776ecacaa560dc8008799b306d5e617b2f51159b1e5fe5daf40f8f488f077cc55bbefbe8f5a61c28ae2b1493272dc6a4e34854f73f74c3442d9c302f96b6e721e2956ee0bcdb9999ff36d74b8d4ef036afbdaea5f977da2b94d0aa9136abd6dc26348873090cfe3d4bdda4d962f9382576bbccf8ba227af4ca8e017f65b469d2e3d35132fac40cdf03bf8f6beee66fe9214e1bf684e0aae75e4141d9daa1c77ef409f56424b01acc7ffda11cb9bf64a9aa71b484b49b9ee82dd8178dd4adc91d8d176f83d2cc7516d2195917fc246ebdc0dba4cb5a54ac6169bacbcd79adb72d593fcc3fa289f1e4bffb4612ba7a3318e607b0b27733cc70a2e2b4099056731ecda3212d1719a6902cdd6a05bd70d389da1dd0d0b4f6c4968676fe33c6e32d791c85b16cc9f4289bdd09acadd9f902d9a91f1559bd40eb6b73da7a623048140f73454e4ccb4ad65038109f6eba9fa01b0a3fe1af228e2c4134be136db2b029879e101aa8ab264e554818450734eb5a900497d906e20d36eb3848b092c778054c5ecee767c00185ddea39160e4513be858bfe5c7c7febf97ee8e2b2fb477bfb10c11f3b756c0da1d87e3121ab4454016b36fcd8f6d2633c73d4528221974b3f21ed3d464d47bacaadbb4647320bf0bcde38b0a75b6c3aac8b72d3c2c179417d05858ae4bd72d9c16713f7c116dda3ff8164710d4d14964b33b00b268007f8cde2eacea5108fed77d7bff70273f351b4e160d28d02576dd5f3fc3ab264c5927cddb6f9a81b852d24842bd5db5c5f2d893b2f013fc75426ef2414bad1b845ba7833c88a8ce76fe2644455be2ac1b9d1e31791693fd65f1ce35fee9d17b42b444bf1277f2646a19d76952b3fa3846c3d258f9a1835a709fc21472b0f7de7a729111e850f27f88764b3ab4baaeb6cfc644b9b6a552a61a7286b5af8011ede05845cb9359232f02ad8b3605b00cbbd83069f26b610378055c004a456c7c44606125b7b076b3f955117e03eaa514da82a9650e8b9247902c5048ff776ecaaa5ea57df61d726ff1754d4b1393933599edc49617836ecf78cc7dd45750b666b73150496e3999e339243f5644d5a3e57c6cdef2ea6c967f8bc93c27aa56ba5352666ab6dbccec415f610bcc76879793935df8e594f5c6b80dc0adcea1a1d5854f447604c54dad61cf0ac91d27ef963e6889075163e89cdec0aebf32080efcc58280b705a029511f21d311c1644623f82039e096f7e1d2518928847abd479840b65cf10d15851976e47444d64c6d4425310a3b5efe9b584ce7aa01b1f79d6e3092486f91fe75288736e852c0132561a7616f21b7713ec53f0dc53432f53eb4ad778dbe14664b55553ba342eaf94e9f76320f8f658b4c5173ab938fbbfe20c9987318c1a5104efe41419926218d30b0c97a366e60f6d1240e7f601a1b119df36cda11bdf7fb531a27979c9823efd2a75c70387f0296dc7382f570fe59568afb406a48e7c13bcb40204c92cfe13b3980410b229767a5412a7db82845da135cb6d5b2f9f5b22518b2115dfb02115fa1c4c3177a55f5c194450f0f0a518df7755b0b12eb412f5f6ee2256bb95d2985bdf1257769718de9b4f4281c3eb3407f175c0b43fee6b94b00875dca0983ae763624bc4e84e9a78f778dedef5eb078ee87a34941005c15cf42ee05cafe098005b1770ccce4e59d9d3f6eab9fb2673766d9b70ac11cd6d8b9d00809e58a046d95ff62e78a8e5525af54094c907019ec661600ec2c4ce5337371a1daad0e37f3a5cdd96a3d985456a588b5c1f61f36a33c6444c3b67c445bf95e9035cd4f77191a95a7e4c20715e55dbe43196809123499148a930321e7b2cc7809cf517fc4b2b0b49e57cde4b6aae620fe8cd0b38358685ab80061c1c126a1f3a96ab34fa957236cc6c59ed962b3bb006a1c122da796bf6bcf7dbeb64f4339c63d3a437b5898be19f6ce62024cf9b9c89964569f176fb697430e553a7c0936056183223fdab2f910047ad5e64098a44a2edbfd3007b0b5e4a5d1e6ecb44f137dae2dfc45e96f03e75c900f3f84e2653efded35a3c8b27e310dc361c0740524e52a1bbecce57d59c4913313e62bbb63c95a93512bf09228918bbf921cd5c62b8914b7142d6abf8d632c3ac44ebb6936c638d56cfaa7cee463838a921398acbbcb44bce621bfd81fab34a8ec33810eeb89fbc3cc469990089d2291e1e873b31398f2799b8d62d429b998422ed634bd7a6de8e991ba8492c001fc5df8b0014fda377cbc5ac74e40d50773ab5c2b4d08dfbf3cca590a77f4db0380fe7af822207aaf99c38676327ccd9aad50b2d4db5aedf74b1cdc50c484d455429352ef0aacedcd9792dc26c66081c28ecabc445b6f1f547a24403e18b0468c8881bdc3e82f7bcce254944271c3ba06c80555c8f3d2d051fb6007507eadf8fb991f45c0c9e9ff08838a425a96d72fc20d642c2eef45b4fa43e7b380d8b6648695c0b9440cc66665435ffd3df10fd786f7638e13706f6c5651dfe5f125158ff3d1da84cad23129e11d79d0f95548318b1c794990174daa895e4b984c175136185be534ed6bff9231c215fbf6bd297e24f528cda523d62b44aec15fdfb36281d804625db07567fdb06779325987f69f16f19df737d5f65d1abadfae70a1a4daba5a87e4ea3a09751ece2ec21dd24f719b1f57e795819689c8f2e83beff593735825a1ff8e4e4df9d031dd66120dcba07e6bfbf1b0946b3585a5eb807c1632a75353e8f7b8c4f8ff0af978afe2bec80d3b94917773564d7efd92a79cad26360b599be49bc657b132b25f459d58166110fa626cf1731be419105b4bd235176d60efa939fdd8dc213c695674bca27f161da4514f646f33557aca06189698f2953674ee73be89e3fc4c014877c6bec370ca1fe446686200a94ded3382c4f4bc58cdc12c354a486463959cb91c2ea0ae965f912364c5d98acd40ee312178b479b540875fb2a0164b7134564bf7fabf59add993b08a904452152031a784cbd36e19a47d4c9371e7774d3433fecb5d072d059b01ebd3279ceeba80b356e3628874008d801ed74717c70a93411603f1faa3924414665a95c475ac42de8d616de8be5c00fb90e5ad13079e54d1c7000905b62742ed70555ec406b49cd4aa6ea68342aa7763530b180e4f790475eefe1094426b7de9e0163a4990ea3494909c6c6de6b7462d70c8f2dca3152d81c93a8c184b0c54da7fb604f835df34506731774e6b8f2361586ccc17f35c8e21795ccb68a5cd73355c98a17c9ae35ed22f6c0a36c4da30af96ce7347375144a80dd851fda4971f20e9d6d18878d74803b577af4fa8f34c05b380acbc5282eb63f9345e4dc1f9f0cf8808a204ec789ed31ac9f009790d5c9b7d744ee3b29d911014c12b53ff691fce0ae5d53dfe1c7a367e694fcd2f688d46758ec308f3f9736701dd825153df883c0dc539c9dc3dc7dc9a9a35f453c306fc57faf76451bef45889e4ab0a4a6dbd377996c7cf80e0e7192234475d93f3f813197ea2d3fb112c2e97cceef2000000000000000000000000000000000000000000000003080b131920", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 24, - "comment": "signature that takes 4 iteration(s)", - "msg": "0800000000000000000000000000000000000000000000000000000000000000", - "sig": "70094678fbb346b4b40e967be25e40f3fd6db4e03dbac8ee46c962c4e7f7c4d2f18a7b44df87b89e8d101bcc264c30d32ad4aa54e27bd70a4d7c4717653c19887afbf6f2359957c895ad477f7d9964e1e941092dc4fc8fddbb77157b31462a46e84f57906fea21df705a01c46b01f3212d91011e0798548ba8eccede6f4d9bbd16d787f5862b6e4dc3d7328511b199c32b609cf90599f90e156d2c00a97bae5b801d80479e612ec53fe59d0e5e6d7c2d2cd2a86f1b0d8caa3856bfb437ecb57ad2ba85d21020cd31cee7296909b19a45cd3303247e4e918db4bae21314366dfac729776c17b5852b000f9567018e7d052226b3b28fb5512bfba7c3da3d1cfb0c31c7cfebdbf5a4e5009ef76cb73316f6ab64570d84c39472f85a7f54918e9fb003a293c8d2787ac533b19832524e5956a96722db2d429aa69e15f3bcda7d887796647f913d5d4de4fcac8024c8da8223f62c973169cc21809943114b6766d3179a17c83e58a752468eff1d23f04f05d844d0ed40faa81bed6f1750d8f15ea24b69b403e12213c2291419d04555c15ce8c1645669f7c4f46f4d26ed4cdc4655b6d6c61c18739163c1f6290a5b535601f345e5a1564df056a9519a3125107b7a082a4c34dea36bc7c3d57af69b7bef90e5ee02426b96dc28c8300e1207b7df14c4209ecabac3142b57d059081da49cd4221c1fc4a159a34bcd95149b73d4a9d9d7f25014fc011ace2f814543922e93737ef968e8e20e8983d3793d733e24cda69c6c36436cfb658bd0d1cd7102686e33ea1626a61ff6662a8be36d0032fd6a2893f5386b471028044e5aa38ab71d3d8f43992f7eb196af9057aef710ae149dda63781d269c248a3c257dc21e30c7423d0bf7322e4f87780f284a92930842feb15c3e624d713a4cdfa5fbe9675cc9b1bd36707285ae31038d419643fa959839ebc93cd66ffaaa720ca4c3bb2b109dcc2dc890f19fde05966ad0d648a71e988ab142b6acf0426a19bced43dc0c83a38685ab5f255e00ee0f1d5a7a341df518d5bbd9ddd31aa6b38d129484ff2b93167123913ddf7e11f6b7be7115c07566c4821d12cfc3db5d24591f040608b7b06267048c944b1be8f67607883ac3c645a5746dc107afb8fb4c730929bc6c99b72b701c46602efc3be2dcf7a25c21467a6413778208e58485b3a7ecd688a97aa85f9ae2f0023d551a970c7714b7bd740ca173cf0f787ef7f961e9f97bfa5a59bee561fba83bc19d0945ce0b66883e5288e4099b4809124cea9426e81aaf1fff02d350a2e9876754ebbd6dda2faee542e768d859398db6ba8323bb4c16c0454020e97da1edc2be24ace53a0cdafde1bafb69e8ca06996c132a19ce88f7693391e2fd1e6483a193244f2faf9b1cfae1d511f34348dde860c585ca548bba32c13165cd3044209ce59d10e30a0bdaa68b8187e0fe6361c1ffae271c6ce3edb53e1f9cacbe9623ef5a6dc21ec7ce626b1863eab038bdd2c1290629ad90fb59de197b4f1cb1368a4ecb05bbd0b58f52fd8ee87591c3f4dc08c06ce8664e476043d4e85202a51996f9c0e5ae2c22ba95099fab8447ad3f71aa2aa95fbea73ea99780c8804037584739b3e1d7f9d63335c9eeb7d5a76244ef7afd8cda16c47faab70550ec39d800d51b1c8f85d366d016fc16c51357642d60d21e3f45eda3a7ed0815d7c585096725151d3a82fbfd90b8a609b6f52e0c18e328332cc0de273a5cd4ea3481913379aff1c03ec5de2026321d4bbc4fd13b1f5b4c5bce87a236fad1ed604809ea2378d9f3cea73c45923d9e4eae4e126792825b883f9d46046ad7787bde86b1745127812534955bb6ed28ebed29e65030babeada913b8b605a636f088d90b91d7166f5e914941d4185002b3aa6e38b312d384c24a4312a8cdf22846752a9bebb1655a3fb904b6c0f1224cb2a83887bf218f339d6d86faecf258afd847f73f5a3f80562e65a07a7c9ef1b43fd84b40b55b000e6c3d661e1fea1037e6b80f5478e744e6a6190226f7ba09e2b8bb89c8d720cf36b9c2bfd33dc34c22c1039ffb71e2f4275dc22c3488744c4b7bb7444e5443b211d3ca7f687e7db1023082483e5ca2eaf89a7eb89f993c194c806b331e905da74830bf8219e2ab6dd80620fedb6298c5a772597dc71a274589314632968c82d66a89e9433cdb6465aef8eeb33f0e738276daff510735089100bb9ea86711e5acb9272e7dcfb512ae2c3587f9e199e9a889566323a8e31ff6cc623307e49920ed9b863edcf54bbd740a7e93d2e8ed71ea0c321ade6ef7a068214f73ce8809b0816f4f2da5bc23890b768324f86a29552af095137854319ae2845ce820633457678072748f9dfc53c26c5e57bc1da00a635f2f7f1343b8adfb83bb3c54a78640441ee244b872d6c86699617e6d7cf71eb1cf0b8ca6bbcc89e3f36e0b64dd7b150604b3509974f65f1ad0adabe6dab7634dceaee4586f6628b2dae7f49663a9a25ed5bdc91b874f893d2fa54afdc6174da985fbca021315f10fb16ca6278521c490598c2e9593467b4af9ebeb822339e6feb7914c70ef2a127cf678c90692b1dccdf79c86df0014bd76aef174469bc904918c88d0acf32f5211dbc9ab007522ff85345d41e083ce7e79e14cf16dcb934fdffcf99c8026b546c2bc00fe356cae580623c74a00661d2a18c2364737e0683a1f1dbdb2e3be4a3de06424bfd54b820a30349d930ef2a4103d3586dff198044ca9e59bbe70481a3fcc955952d69b9d01c452990793cf3021f400d2ffc4a97fe248863219d16a457434f3056084306b8094cd11f97e48e6f2d45ae9b3b7047deb2e13c43fa0eb8fc710e82f29633a5d4f065986d66323884fe87cbc66c114026745889c62d254928257e68afe0e52e51e25f337360dd227dba3ccd54f1e99dd4c704c9bd126310e4c72160da70f176de957a340fd481f84c1fca83af372c9fc7f2555baef334614f02068a820cdf2b9b1b440d0b5337f4b4a380e6d95f423ebcebde2b455ff74811ab431b2550fcef6c6c671bae84c910611176e94f0b2815d55e7328804a1ba1b490b7f86020238114a063068decb8b3c4d6ae62f6ef6e8767b934d9cc817fe50470b9f0a6733ad446d12a115e28dbb8b610f01dfb1268625841efa796378fe64293fdcf859f38406dd11e247f41906cd6c6c9cb2afed460268f78b170edbef056fd2db36bb6937ed3bc52bf1fd098af62177ce44723b65ead8ad50df2c0fd89df098dc56cd51d5a74709c5cf1b7a09683817f0c12ef399e83f6a4e8a17126da998f0a224ec2f198ead30c543cf403615f38066e9417ec3f2b865464f8fb1b7ac8c3fc6251aaedf16807ad851b980ad9db62ac0e07d9b856bcf579305d9eb66859e460aa269f0ac69c9e88b014721c906a1f3bc8a1258e04683343f2256fc7c81ce17fcd93395c430cbebd6b0544c11de1eb426927f172a2f51aa78aeceb83aaeffb1b62b66a13b19c0035ba1c41604441fe22ba1bd8b8ea29547599b4e00996b2da1e937de02a58954cd77ab29c68ef2a03321fa2ab299a2018d625de8f65c1baed074ffe2577fa5b0a4005aaf284e7e3bb8d9fc365ae978fd528e0c427d43414b14ad6cc7a28fde2f71d1e7187a3362f89e2067b5839a71df40164c5d5059d9bff06535d317e331961f17bc5800455a96078be095e8ef8face39f58f62f0991ae3d97390da8c69b900cd47d749a75e7b7cfcfe1d4ab3b01eebe0f4a00ae2c7ebbd134e731075b83dd7eb726daa461b7dfb31d3e0f3f9cb15ead0771ec9193bcb899469100dfc378750dd811bd69b8acaf4c646414e5385b8737653eb9773dc9eacb89349e8cab56c3d0fdda5d646c82d2039fafc38b0aaaf77b93d86b7daa2016c0911ee6f46f1044c851176ead85e775ffa9330e904d28bdae0c4820b7a4ad0844765e05f5466d3ba1eb2381284c3ccf0de5c31744acae33720f05b38f7cb099262b94f4b025cda69bec27ed08c49b0e113f510d2c36a39bfb013654fc27f8802f414f9b894d4f9673a6bb03ea26b5d4959bd69c08aeb2eee3a28ecf78c61715751e43d5a5f6d8bc5ea7a70de3571d16ec9b5def79e3b3e0fd61e900d98bb0bcfea8e2c29651d9edd613693dba51b0eff6f8dbcc51b116244f1bf4a14c5ae484fbc5189533dfe011c7e8b75ac8287bccf269f98f2628ee419354b02bbdd9825b10eaeb0dd8d13423ecbab0425c98a1750f3c75738d27202ca4e9b9b760dfbb6fe86914b7cd3876800ea409b65c12dc01e2d81d6a2584332e63be08058566543b064bce5673b7dd9dc4f69c45acc7650291ddc87d4ae9e1723d51701f3fb3c11376019a53ab613b8b7138a83fc76cac853355a1b713f0621f8cdaab631da8a0941c58c0a934cfcaae84cffd95ff7e831cf38185734972942549b74d9c67beded7174e4c76d0ee55148443e785fb73955a582e9a94a14c621d6d6cca5b9f270a84b030202db41000965e0ad66f5175124f211064a2af0c36591f16734641c87af774708b7b7b8226320b34f488050fdae7555e0fffd1c124986ef03d2205b4b809514e5cacd34e7d0dc8727772fce98e0e975c64ec8258e22a94bd2d085a6c808c8fc421346fa7b5e91c8287df545b1b3589a9073877c2cdd70000000000000000000000000000000000000000000000000000070d1113171d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 25, - "comment": "signature that takes 5 iteration(s)", - "msg": "0500000000000000000000000000000000000000000000000000000000000000", - "sig": "604ef7c921fdb209de3a95ad6c032162ffe69ebf86638fb7e5a2a9eb3ba4b68fb7667f6b5555d000e4ba05a2eb6a4d324b04311e4ea01824c1d6cd160802ffa20196ff1b0f0c1789ede25d58bd01930986817524beee3d93b1fdcf85a3479c7086029d04a3ef378a8d4658310ccbb441ecf9a273a50a7d57d2a58087fa0c97c0b31b9abd8246b1e9d46e1dba106e5f1b5682fb9f8c8c7a8a170b4f12fb5b2ffc08514d7f68dc81d9005283abad65299a75421ade87ef90300d9faabf7b9a7ac3eee8abdf8269946b0d3fb4cc674d58ebfd99377bd39f63c54313995ff3ac36e8753637534b8f913311157a149db56217ef758b65afdc3bdd7d2aa59ebc42daf9aa027dc753f051db015a9d8b6793ebf50094dea5f38ca7c2824936f96981fe5c75032921b6817b81776e28d18485777cf6e96ce2a57a9663d30d804a2e07e188b77804eb54aca4ae43f3ba71a3a07264a1a1aaf6edffdbbe37783e11ae3ef0b3e8f5093c1c6566366e65c5bb6711d706cf64b1f579a44fb3a267cf962751d66d46c0208d1705d535debc5f969c519ce415731ff49f93543b56cd2689fd1f94c57b6268afc5135c3a92eb3856156b4918e79bb690b99898cf5a213d63fe0a1d5aa3512282215691baa6c6da5c952f9bfa3d11c4cdb1ebfcde709e5c3347fa6d990e9d2d805d63bda508ea9e3d4e0bf2f5055201936dcdc360900116309970ab4ee0e943248f021e2acfcd4d7f7696dbe33beb7b40d5deaf042ec6cfd50f45d65f94812870c71e3c2b61db121f634cf3fabed0e48f6fdb63e7087d2042a1bac7f2c296bbdd70078303f05a7974e188480d6cc1a777576597afa9429c3c3cfe549fc41887993f883e4d823ba74a79075dfe5a3a26d794768c27436ec5f619e3ad605cab8c894e2242201f4381d7ab1ea3fc346ae17e783e53c95ee2d9bed1942e5f3f9ba65277ac7a0658faadf48272c78a8c9e38d6f21be59b492f4e0c134d965dcedd49b0af638ba010f8e2df94484b97094f63bcf8660add7a05149fb2c2753d06bdc4196e2c18d7ecdf685358ecc03b3d67b496828881a8f00cb16667ee52a969ab67f6e2645da8345d86d5748119cf28401d369270c7aafdb3977de4ff328cb34147e1f37db7778aee3e08a93523cd5ce244c78acca1e2a7b1f6d72b76fc86e7457e9de61e473c605a305fdd5591c16efb499c5e5ba83831d202ac14222b802e8c9941522fb0029b43e9f1cbb6892994382230456e899d60655f9bb29fe10811098a0de73a4ff87da05d0edafc2fd7815fb1d87edc40316ad7ac11474b68b013430c4023924e021706752307788f0309f86548f9deae7736431e98ba50f3d66b3036111dcbd1f28a51c83b1582fe61eab90efdbc9800f2493973d1fcdcddaf29b191094c67cac62dba01ae2c82139e65c29d11b927a3ee0bc93bef952a77c6dcb94c081ae022bd2d70629d630c7db08b0318c915cf123416d6633405703bb670694b4932f716c67ea181f4aa56ddbc781094029837f335205bd4eba0d3fb0e852d4a80e98ea119ac6738af8bfed0bc83ec0cd4b01cb75e1fb73f790f265908bcaf0fc3f3ef3549c149688ba16fcd5033828b2ccd46e22316bcd91e821231111b9869ff2257e996dfb26e9ad93850d6b607a5a5d197bff5620fe753f5b494e21e44d8abd5bee41ae8c81f8f7d0fab317c347e7d00712552610431242870571ec6fe77c1df51f7f78c353ff85660b196ddbe065c6f361a9c05f380eb18b50fbe0a0daa33cbf70d03e9b399e9bf3414e4eeda59ff295a6c5aeb40b2b458e21f43701e625a93a8b047fb221cb3dbd83a86b03ed9de58acd816a58e0dd571edc95d145564fa86564f86aca2c61f49ea4a736984ad58fdb02c0c105843c2327ddc97822d66667b9188a6e371aa5e09110b6d72854d0903d432c51f13b4c61107a7a197602e56b8dd522985af2ca20af824be8d503006913f6537fbe4e288c684bc82144c6123e253e8989c59bbfc83f68a9a8ac0061f2d5d93c253d2ac9328dede266eb44b1f5f9a868ee5052fbb2476e11f9751bda60c8af5f1cfc6e8b9e1bf54ae2ccbdd676e3f5158d174974fb0abccc3b47c1ef353e12600a60005a8732d267e33b0a3ddf7d66e2494e6afa3c135615e4183b3f7be8006a5e2c3ba4f1d948d1b34a320113faf891d93824cd38dce7e0c795ad623877839964555768ab7aa776cb3ea18827a752ee3e7c6b025bfc48b8e8c99512578d2504a51fe29103d93eaf7728652dcf75caf53ec55ae9436a5d41995ea9febfa38c13299f22acea0f59d15cff0a88a4750ad68d2750fb8ac550459e2a954141c5b9382e2de8cb83926f2ce102d4846accde022c502247259918bf44caa8f43c93dafd89bcf727548a9a30e553ca37109d85a6923b42eef083007f258d57b1fce21dbc830618c37257119592b8e8aeda65a98f9cf6f7287a53a8a2c64435c212a1ee90f52ecb9381b56d67592395dd8af5325a09f643504adaee45be117dfb70d92a3ebd78da21529b3d0af76eb71b2f13dc3e2755be1df35dac40c0f9c1f37058c249c44f09a3a2602017e7110760654f7945d5bf653119e78455586a6405993ec923c28909eb7f398aa02f30c1c06b59be51b9fa7645bfdfca98e18793b6e09a89e9e76de835df9a0126cc6ce9973d2bd32029f62e7026df3a03e9fb4ff9ec1b3533eb43440a290df0216b6a78d13d40b094ebfd3797c85514c9f3e57f03d4499ad7e5b0d3f91febdea51738a9c0bedc86df1c80b90864e3710a6c3d328451f3275c04c9702861ff49824d87828bbd5c1e16a7ae950ee2896dff2b82de43a937e31e2de22d81448a682b70c7cc8a71493b08a95ea8a034fcc5cba59b5fb09fd1044b649b192c76a9621fc329baf425c34c30285adf948587bd2757d733a7ae82bb7c71404e9672a40ebd37acde5c0ceca7febf2166e599d8efc1080ea0e9b5efdb3c1a3b54fa24f10c4a706387b7381bf094265a07ad9c85f18cf00d92c66e9257515c131132250c007fe1a39ef05529243797a96370fc51d5db7322e447d834fbf7fa09d136fef12dcd31c3cd5ca35616d92342013f8bc4d895ad00a27a8e641084bd734f1617cbb0f243fa83230393487509c6041f8122c5b0cea200aed694ed603f104ab14b462c722476bf2a95126c9f6bd9242c5ca6a264572700850b33e415742a31cbb85adb1ae6e6380f059441b898d5bed3d64a9d146f3fdcafd788b9f65497d6f547c15b652bf70844848dfc003700c2645381e6070d314b7831b1e429a41754b0ad2fdd71348217f35711c56271a6d7bb4ed15a765d06ce3f970e4568f1ad60af3df6cc2e385fa55686d3633f3c82345bb0c3b539ca8ff2125fcff6bb5a4e3010e68515fa28bc1945a255ce12a391e0e4ec77ffb098cbbc2292696805e8c4c3978d3b4863a6cae10755d2fc016b2a9ec2ffd5c8d3c5ea9b36ee622040e189c2ce167fa90d07164d70dc5e5d3cd9db359dc5b94a4bc7d6619170fae9ec1a82996e0b75b6902ad473255f179edab1b3ad097ed71bcd873850d2e94223c903dce00557f616a48661ae937a402d2a8a5e1f1f6da8641dd423ffa54672bd9adde84ef8798ba5a8c79b56dc2e6ff694fcd63722be9c9146743bb68bf6a8e0d92376848f39f81bc4e061bb8cd63a6d7707985a95b699b37dcd5c0da66ca9b8c7912ab45c435034b3b629d3c898f7d979124707817548810f07658cc72e82af5ee86c28a89bf070a80d2050b251a0dfa75b567e7decc2fae12b50daaf26326f30ff072c1d509eb59c0e523669264966436d2d14bdf2538fcd58495d80c580d6e3343e9bec883033c7c32fcc693eb123383ce7eb2ee5d5b1b09ceaca617346754ff30fa9cbd3e716620bc5219a56111aa5dd6d0de5e3904bf22839b0239ed994dfc7e6fb6c2436a950d1b925fa975f57419ef7d9c3cdcf19cee53044d6db371d1c1c8d0c4eeee9e4b963d197265c42dcff55c5281a742d696292ba462e622429ec0b8dd3f6a8479f7a1fdadfc505d23de0777155fd53e4bba4e2433033c88ec9a8578d9896518db1d1dc30d23c5b82b5db14039cad18389b5dfb6015003ebeeba0e2313045ef1cceaced1bdf0e0721b8fe6a636f983186c7f3c559377e88ed149435bfb8af17e3cd1ee277b0305a1717a0964b0eee875756ae0967c04dfb051933c5fd706ea2ac35cad984553ec63ea554246a2aa10266100ec88619edbdc3cc72b14f2c8a12504336dce5fb00517ec36838a5ab856ce0929414d3962795e0a4ae7dc80031bf5fb732a092109eb3a119765d69f4648e0e690898608176f8233bc010654e01d12844291722a4f195f1cacfbaa5b4ab674cd96efe868c377c577eb25f81e44977c928780d49ec3e52694e2c9e8fc26a8cac64bc927a9cf0dd90f36c11685b172c10ad7d9cf9d0aa4ec26ed6d982c90d7e97123d9cd67cf17198e282934d0621702d22cef8846c2dd4b4c639410f3da93287f4c1929638d1d624be1ad01a8e5364853556ab837a274b61800a723b03373b3da771d0949875ebba692f0baa606d70046c841fa16f191702dfac9a48c8ef9915a0057234b5b6999a9f82b424d6b6ebcf9101c28495575c1cefbfe0517303e414c5b5d8ff70f30649fdeeb021e3d41476f93f300000000000000070e18222830", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 26, - "comment": "signature that takes 6 iteration(s)", - "msg": "2c00000000000000000000000000000000000000000000000000000000000000", - "sig": "55248b18f7b86d8cc873c73d809b0453f5db7b7aa436797c77fa7cd51624c0a8d924808b8166aeeb2cb3c2a013d1529e21e6b8a4a7ed13caf47861f90399a17277953e2505fb1fd03b16b5d1e1e045f2e56f30520d3196c1e54ae84bffd80cb27b3f0d11ec93e3522d4d3f9b66859311d3b448412816745f34f4b07b8e593be1bc747f4eb8e8e20b9addccbc4db5fc155afd4409fd5c8e23399cc55bf67bf9c4614a44f1342aa58f462489764491233edb1bb8c4084fa605d39028e7ee7f8e44dece7f58a28d09665624fa0e0b5495a43b6a623bdcd0fdb6d0567d446dc6949cceaa15cad8f3f3e6ee63de3019f6f5df02bbd7ac5ea6024f4dfbcc7ec4fc9d618b2cbeee7d72cd5837d6263a1df0f6bed8708d66be35e474783d8f39cb08e130d300fcbf0767dbb4c6f8ab12dde570220f1abed2bbb029d80a927c51620d5679e6a4bcd2d34a4906ef8a0b5f7b87082a57b701879a557a989dcd255a2a845f2b7ceabbe05e853c6a36f8b3120b61821cf8e557a4a487e5065be0770ada01fdbc64a607e19b975b3f90835acb28a023955a713c6022a593208cce54a582329e0890ec4fde395d5eda4da6ae5f17578aa1552c84648d7663873a7093745b7550096d5da5b8aa25e9750984f74d6bab5fa9c751bd828f455a4784844cf8db1681b47b05e5f6c60364bc647196134133db8b2d672f290d37e238f562bdf52e35980e8d94910829ff7170bf403a29f210dc42e7ea1e2168c5d04429efd560ba9c11b21e9d8f081503b861e2fd1d832397bf069f699221199b395015b2e79808be26c9fbf6e18280c3796f29a1e0a4be5cc9901c6b31c84fc69abf3bafb07745ae08fd4362875832ee768c378c3e387dac8e06b7578d8752e3ab4ad161f8952354f1569288d9400f28603b0bd7e239ca2de916e2718653673236c1c3f172d67fd9faeca57ff3cddba66f0f589d297b49c311a75ece1daa7230316128f28985210fd2f1725ef5b976ad67dd436902c7fd6134870da02866ed96ec997554a684216ca9574264efd28810f59883f5f73df115024d56871fe24d68b142bf5906fdf3d3839660ba7d26aa6827f47a05c80f1a62254b6cdfeb55de694e723851a3c2ab89aec1e312c7647b1b66acea5ddb7ae62ca71c4bd5592381761fee9d85c38f2f42f54f947bb3d4ee340077fc86cbe19af332c96d67f8ab84a1f0b0f039f5e6b518c9f9eed9edf2a88dded19903a0b78e17353fc5e1485cc722dc9a0b12501374db57b4161a12852a45d160ce3a21a44a8e37cb8dbac3d3a2ae131fadcec0063ce5b777df45b67744609da238f53aff0ff8e1175fb11a22fab7fd016c41f8aa636aa2ab7c4508f445b01852a9944277309f7c77d1f64048dcda6206293f89f914152958c1ceb629d7991589edcf3e40cb7a75090cf48c55f1d16b98fe26b55d31dd860b31e077af05012c8d4a9084647741f6b0e667110e9cac2dd031c1e82deea92569bbc8454f586f415c08c18220428fd25fd0e06517cf89ce7673961396f992a0f395eac5e3ce1b81a77a78db440039ce36670644592d36d43e1f0338d8f54fbc5c97c5166d9914d4837e7d005269529072c6b34fb1e5e8ad177d8e92530395896584aa3b587cfaa74d4effe70578d64c8fb4e4920528ab0bd4bcbadf344a148c1ee0c77f28dc6e605f60093948733fe8caee60766678580ad00d685d932ab692e788f37a54342d0047457cb48efcfd994c47cc57cb4abe7aca0508f3c5551c51d448a111ca477c16a0018d1758599405ea49efa618a164d2220dd714ddf9832d1c7d1830d93e54ebfe9353d5a90f2a255ab1578199c3e379aa4e6acf2ea07aadfe7c8b2b59a7149feda9c35ea80db44225a081a489a9f2ca447e6a577d87fc46931e01e41b67485fa59951192ed7949913243922ae9d2178b24eef6c608113e8ca3972c705485b3008cdcd6fd7bd112c13ab780214c47ce1d7141f00a4c06c6c8f9ac508e01c345a940ae26d374667b1afe9c89fe5d7ead12a5011ab593de9b4f5bfc68498d2e3dc6d1cbc4b16f7c36c30e2f1b5243df73230f4b61ca4f9507c0c2092d7eccbd88d3129db25e76ced278445b7bc91680bcfa73c89c84623cb32e5d9ee335be23af54a54226b1e7a542e75d6cbf16faec7867cdecfebc5483b4b4bf50776f87495d0bf6c596e382c859020556670d70af2272f816b3881aadb663eb91ba95f31dc17ec606d64a55f44c12a54051bc7119fa3af23ccb55ecc9dd0875e8aea1da93e78c77096c9b81c24232a6f64aeb949e65f0527fa9f9d86d24ff1167525c5ef0ac2c6a1cdecbe5c98ecca4958d07c80a5f41b2a645fb78ff17828210ed843f3233913a021a7b5f187db60476fe139b89217a942da48201f3017d704a9e9590800241501fe6526f0e3e05af68c0a4936bf317375d39e19d502cdc938072403516844efffdac2a1758c2ad1ae29cf8578356e666b5f6b60e9198d847aa0c88a903759418bc0ac2eea77802b2a41c514bec3149bebe8fa0339176b8380e5b08fdbc390e726167ba15757842c4c9a8d1a8377811f9ca3906640bb38bd3156dc2676eaa49cf6a4cc90635da341be52dc7a7b3900ea89c697f450b6dfea351cf0b0673ac50c72d7b2ed3cb45b06b856a41c3603bb50dee0ebe272200c6e48a33639bc6369963909c6ac67ada94af7b03dade60927f35b97b27a5251e3819c71372bb6abe636966323f0abc04e26a699c46fd8eaae6f3b4b097cb40eebde51f6df2694f14b7178102ca2448e3389656442febe8ddd6d663710f63a8234fa6dfb6f3a9f9d0f69042b59b58066197ba83536f4aaaeb4d9959af819b40ab43e09e140e883037f5e896a5f747f0b70083c4c720f017a021a12746c72e231ec86d684a99fc85f8cb73dedf83d23f9aa6d27877666670481bdd97d428cc1eda80e4c08ef00353aa4c371c3f938c766da833a76929d9c78b34f540381909affad1cc12667e6a8dcf644b51e968512d80017b876790e58c464d222665502c2d1997f67805232d6e6af2b868a801a9e32404d30c02b1fd8ea671daa7e97ecaf72addcbdcbd2f6be3794ba20d938a8cf15db52ef323ca6b47b644dc93d82508249411b9aecb7ae10fde49fa1b209a2160581d62c10962ad419c2b82d553990b7583106d153a1ee63df2a283484c6a0ceb2cc71919d00990f7bb87df0e6c4274fffd98525bb325b495d860323ce49a2df510c2421904f4bd3afc9a45a9ba84ceec0b8de7f77f14ffca522b424778157bbf0ac8e873f05837daf02b9b158c7853a45f279dc5238d202403378b8ed8fd1c69ed29fa4e5eed31a2b803cf0480425bc7746bf39255810e57bbef7cef25686c0893271c57feffdfef6346552e269f661a6e396ee399ab69641e7ccdc87e1867fafe8a754d77c7c05e49196646b21b06bc955b4ab287a4fe3d0749fb65ac042408513a736e32c382f9c81a6381d03c7af37a54fd3406f278e4b4f58b98f3202d7340933af471c840c0379cb11a3afa691d6f50ce50c20b02623b45123b75e8c26b64a221b5c36f3758050870413efe61e0d8e7f7bf77424b3478240990f9333f0ccae39fd1d782ad05bcd1aa05b0b6d58fad5766d056a4587ebf5e848a8129e07bfeff86ff50547010d4378b9b1f565a67207be7571c8f330f03d5ee6edbe06510918d7e81aa916cd49184098c99959fcab3858e6bbf2ddd62571be3869bc1f3d7e559c657319198ba47885c7da9e350f26b4e25c17d27d55bfc7e6813b6c30cb1f8e59cebc5f044e5d41f59c46c317d7020c57e13cafb8931049caefdc3f296c0363af7f7a89ebe18c0602cc19e8dd4da1bd14f296066183e80c03c806255a5767639c1bfca3037cd7efae6da14cf00b33f64b1021fc0a690a48abf5c6a781560a86d7501f8d0d05aec20881d23efa9d43747e30b262a3c4e3da85283cf5cfd94cf4e485ea56ae0081bbee0a9f41a333ae2aaca92c7dec0a2df94f47587e59fa21f80624a16e6b449194d1279ae5ceea47ab02b465b8da93ff50389aae3de69f5fc8a0eee992ec43e08b55be7dc9684264665dcea7ed4055306a1776f531d2a386e2e839bcc4d6e47640927967dc5c2571ecb8153827c44dc0ea5a60399a4a285798893fc5e9ebf74dd4e42575316bebba6173065e6583bd69d7f9ad0b8b9c6930c1c4198c5407f06008c9d04b1002bfa3868a8f7ed20a1bcdb1bf75a80bfa5cfff2a29b23e3fa963c6d7618c772538d98355d82905a66722824ab3a2859370baa9ddaa4f4ed6e6676528275d993bac69f66b4efeb8806f65cf8491e61879f0dce6bea760e2b3351a24b0fd65857c5aa099954d42ee9975b7c32b831d97fa862fd8278450d8ca34bb65a23758acc6fb96a81a30f1f28f85af5ad8c7d5868ba908da53e8fd0da4eb182a3770b68e2d72576ac7002ff348bedb8eed91f96af6a6a46b99e5e639845b4962fd98cad0112d74a6fe57fabb250e42c136c34a199e1923d2fa1d1e16abf8ec661c4f3eebae21627ac62a8eab8ff872c769f4b8eba495cd16d73b7448cb0a205da2c5e78c85d53cd78bf841cdd8f94cf16666615314fa389de3a5b63a3c05b8b939dde0041496372758fbe006caf4c718690d8849ae5eb000000000000000000000000000000000000000000000000000004091114191d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 27, - "comment": "signature that takes 7 iteration(s)", - "msg": "1200000000000000000000000000000000000000000000000000000000000000", - "sig": "577e0d1047704e02b4ed8653dd7a36c7a469f50314399d9b1e07fdf02a5c8a6071c4f2df79688c1a6d32ae9182279c76311762aebfb94e9410d1a74ff0191784a9d311dc970ffe4b51834e9bd49bd21dbb47817df5991553b6072dc547048d58c7644217ed1671c993d60f9882359842b82f48c619f318ec138842e4049ca3f0592bb06b14ae50ecbcfbc2a6e7c806765d404bbc5db8afa7e4d37f3a8fdcfe9867cbf66d1a971540e04c80e4a2403a0c9e795cc457c0cf1cdd7897843eef8f7e1642b3a9b7f4687763423ed0acb11270fe0bf01c1fdb0077787c591d20f2deb39ba6aaf3f433c3639a6ec43e314d212eaf1cbd4598b0bfb0f4f778f86415ca66122949ce3f101c667eda97f8cf6fac74d92472ef5fda6ebc1383a6d04bbb41b0e89ff80d7f0439b19b1bc570d8e29729b4d1ceb12648ea7ce092ff3311d910bc3495597f40e191ccae4513da4f24d88d211473468de354f1f03be275da7da36bf18233404f9d6f401bc9835544b1307312372a88714435dae593839d8706d74157a81fe8b744fc6a59c1e05f49628f8d39e0585c1ff156ca8101a53d4e48ba22d99ac7aa3f5e84af66140e57dd068ba296a1850581f6156671bfbe983d17e0e16d89511791b5be7350283f1cd100b9bd3ce62b607d00f3ae4174e892b175934c7c885c5c6b2cd3c533fa82fa7256cbd0bf9b53d009196c49d87779b855be3e97b4ef3adf68f02bd3e19ddfd876b55f0565d5600780733bfa95d58754fe7155ac413d67e9d5b5819c66140c15eeb622c0c8c8e15e05c79ef3c030de87a94f5601640f3bfaac0c961d4dc03b9d313097d20b83d27fb9e1b028503a624db1fb862bcdf7996443173ea1dfe544f285c4a029b6eefc5ae70ae3869ee66d220b89f83cd5879d2002866ca765cddfc8e499bc926dfd08cf86888f957f57ad2273e9155aa00ac4b618620953afbecbb4ffc6e93e82b77dfe4f0c6bcbb4e2f849f3fdd70f9644d1d420cfa938ded26dea5fb0052319848456f611f64e5e9a890a0643ca9ab8bf96b0b89864197d75c85620dd76ffdc0525d8872815b92a8369af17dd5bc4fe9519a2903bd8c1e6f844cca5ca2e79fd08d2b66939ad1887e5a651968f93e804e72dfcd6b244a66332e8358c7a39b337c001708dcd088c02c8152816d3ffdbdb323e4c8909e1b1a7fbe3e2dd87c8a985ad008e54153ee21590ae89459bbde19eedf5a23e019cdebad0f9448a72e12533616b76803dc59bef6a5e32e25caaf4034b6e3340398e95a797a484cdbf1433041522cbec6eac497d437a8374e2954c35e7ef105b45f92418b674694180e3abc3903f9a865bf24138ed0f7b5c81a8e49a39f11f3f81109a4fc9b1ddb6dc0d3f9697c4ad3d178b02373a46669fc8b6c7fdfa07e0beebb47b5043bab910190c1b5680a5e49ff786ffe7e0aa243b58c5fec92c148fb48432d20c76c88ac3b4592059eb414e2bb9d50c8db83f8003542a1a58826dd0d91fca351067c13917f817e32a438c02de1d51c3e2817c280f370a96a9145863a7ac1b6a1ed1ab640ae1acd2c72a05928b30ca51276ab0d3858e6e5638f061219af3fc0795a54d7d81c368898314498a6b279ba111c3a79514918adc6675b279a5571a3c7a9b9d79d725e852c2204490230a0270f00e758bd685885518bb15a456ed6344786dbd5c4009f94f04206e87b51d092aed1aee3473f8211a3ba22a5ac092a53831f37f4d15bf0937b9db11336018030469aa296807e6a5ec829c8b3fb741cbf0207692fe30b1530d545a56a48fdb5b3f72a8f158dcfd4808e30ea8fd7e2d6a19669ca7de2d50015c586dc17a37e6835685e691e516e517be2021a81d42f0330e29e8114fd729dc1aacef69e006f87ad74b0944eeba1687a2288607a3ac930c106049bc7a9435d548fc275b1474299c7bcc212a41d9847caf8def2ee7293986c42af986c0cd28ea70e56993876aeb3ad7900e84daf267adaaf5e9df3877aa1267cc99c7c6ddef01867a17019cc013ca1a921a319f1172500ac75cb8a200df0e38c1cce4054f2b0fbc98f76d4c7b61d6ef3a54ac0c42eb2c9ed53426dc2fd289e71f0532a026936629b6eb8657241b77b94d6ae11c54a9bf5c7ed7772e7581ed16607bc090c05269052fbfcd3653a9cc4fe8d0fc0692dbc497344bc73a3e9044a79d7dee977168d1c1e462b03da281e4124deb377be97b286ad5a1e1ca93529676c25c7601fafbc3cad171ba3265690d6ce37b760d053a0e5adfafa070becc84b59c39d401a4b3b84b80c55a9260ae2bb510230c8ac81433f466757affe6c55d6b52c367c37eaf0bbe5134a7ca5f1aafb745fa9025ed419e9360d1649bdf87696033742cdf7a6804cf88ce19c7d0f33482c83e65aedcf0e3da55b395198579a02847899e5778fd5369a88d04eacc1de1ed23028c4de2cbe5121a6c65cf648550ab340dff5b49e51e9543d6711ca1c3d26a744d1949edf649b81b7fffcd663de4532ddd1e7c2837d6b30995029eca9b30c8e2a00dca5a44fd603430daadadae3d4ffa83fbb4c97a373993adc8216638f0203eac09be5ad7f222738907a1c2b793b419c317bc0312723c0e8371cfcec8a13065df31978751df34ff3eccfb5b37315fb66a506083e5813295373c048b182dca86876528209d157a44a739cc9cb99e076d82f51885ead7933100d030a3a7745cf81cc36639e50be9e067b09a2b0015a7b86446256fbc977ba87ef6ee700528e751d5f346d6c24308403107aa05a95cce61c1e3894a1dfd97cbba4f3a130dd491368787593cf353d3eeffa56640a3451cb9eb207c19de0edd3fa886db645e260618326095e8ea93a1092183de833b66cd0379b94ef4a1cdf87581167db387e0ac24b750c47e02c98adda5a834b9b00e88d9a981aa98bb30cd8982afa2cbd7117236e03a23cf13f6ab2f67dcbd580a1171deef889889daaf156e281eb5a3be2ac914841f2c7907228971981ee9567e18748c03ebfe9d4fa67dc2ddaf865e1abe1182ff33601b97c44706a948f2c0bafa57f3ce3819005b5e397eddc9022bbfef2f65f9f29d86add3577a6fd117139a9ffa190b725d60aecc19370343a82f1f0f584896aea7d57fc092b74c0769c94242605b521e1f6a4cd2fbcccbb4a80745d3f431e1a12beb8af87145b9eb4b0ffd9a863e27b18b07fac43bd686bbf08d040c201ca574baf00daafec8f92c8a37e43f3bdc7ea514f2e0367a29642e2e89947a39c479c4ea940fc3771fd57c37f96e759f333f24c3eb1a67e6b202b459107042de9a1b789f9e9e8013cc3f2a89975fbe6c1514ba2572ed81629e0b418d8011659ed339bb37f0909ba8993475a4558027613efa516e575336d735716ceb77dc54678337a9e1d70b87ac85a3b6676447de69d6bae2a0e19048b70e0af8b767165353c1320612671f17430a5233e2fd95237889e4f11e5fa8ef905fbfdbd09db873acd82420e6a5d0bdd6611e5caa0183841804e19da3cec5a21bb75b91a01a47d7ef749af0fdf3b224a2f0d6abef86f850d16a9d7e0df467f28965c485156fe46e611f311bf59ed3f5d690ba6572228893e95e9e370f022b2daa966b31f41005e184e758b9ca396a23f01adf0838f9987433c87f9b0a98b5c208cbb57f66014f66bdbe793922333ea1aed91419f10a90d5f18f983027b901e5f70bbaabfcabebb53ca657c93b0899950b1dc2c02f5f6ec3fe58a4ae5816013bd7b15111b10779b13dbee751427673aa97e00eb9175dd2bab020e1ac9c9dab87806ac164a5d8f86217a15d4e75d13fccaeccc0798fab7551bb9ad89b2c804ba49606ac08adaed603422726a9c7b4c5a30bbda9d46004adb1baf11c4aee456bfb369390e82d504d0c300b18608da25086bbbeeea9baf586182246e6dfd6f15e2f199887756f6a914ba6cdbbf5fd5029f67212c406f1b5b88c36cdeaa982149f787e273e32be8f713535afeb960e302b129521ed3bf2d0a911908e7471527e7a177748149ac35e20e4d4ecdd95c356d84143e4cb6e627a1bac0cd813c00985913a148806bf00bc1da3b6d123da765a2863cb07b208125d640afa03dc3f2025461d228665da2590e3cf692163c5061c811f1f1608614d9ae6301794d9b35dcf0ca31ce7f475b085f14c6edd944cb343c08e5af9e9680f2e20656556cd60c2b4b3b10a66e71d0eefa893a88b7d3e789935173c39d4a5d6918f3b41187001b5cbef0cc6fc2b75b2cbf7b4581d97ab046f1d926fbc9a900e19a5bfea2989d3a63744443637de57a27269036ab9f35205a6577191f2efe1c01caef6f26c697fe06e7fafc6cd7fa533a76cc3ba9a2ba2b07bb2ae7cde729eea9b5460fcc9dbe9e1ed7d024668adb632321b2a649c2b285a19e2c5b1f18102be86f3181c0264d262cc55b2f2d60ccadb6329f19303a012ce1693a474d651a14148a0179855cbf57d149aea3165adb2bc54a53452f4faaa758e7961c80ba00dae2f3bbd08ef95901f4747d6b36561bcbae89364d090ad6fa9fc37287b5c901bf19504bba36f0a814634673918b1141b49578bddffe2b30331db1fcefe1bbca0ae41ce4f1e1cbef7daaa22929300404974c4db0b132f5dd4176eadb0d02e35555c5e5f6282afd1fa494f6c82adb3bad3e5f4fd09222a62bbecf700000000000000000000060b101b262d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 28, - "comment": "signature that takes 8 iteration(s)", - "msg": "0900000000000000000000000000000000000000000000000000000000000000", - "sig": "ae6b9da548f432f42eb2f2d6fa196c10500fd99674009ec015f6c5b2e5fa39218f361eac40652d671454bca3ad7e179fe8e44aee00e1731df3d0557e2f6b96ea805a7713d82fdd1ca369c868c10654dc0b38916a1559517334ca20021489c6bffd9942aea8c7ea9354e42d2343c6700422c97b882299909dc15f653e6d69c44bedaa068c129f0743b6dba58e0df1e30c4db0df591f75bef4fa209cd3b12b48a7e3cdee1e7e4c54f719ef10611aa4d2a668fa6f9004252eb8623f309069d73b46198ead952e30b5d2971f57d7c983a098d9f7a25c8117e2601d57cbaf36d0434ea72a11c2214c170e0e0db7431490ed801f850002b2f959eafe961971d8992e4f306745c2b7fd7b12f73ccf6757eab25b87e39b0a2ead28e3ff3096c706305d880df78ee77cbae24791796c05b537531e64e69eb71be60bf60d88c076cf0cb19a6858d435fc333d962a668a979b31a8c96036b516911290d7ec16b6f6fff2dce67fd4ae815e658ebc39b2a35666a7d1fb2444c905bfa913bd77146ccdd33adea9bb35ad871b8c97b9c2a836721f967e62382bd0c62073fe60b2d3eba75734ef612917b1f7ab0cbd34843fb01029b1b0c499e808095a90887a2612411d6cc8f85020f3b903d1231f5ad3cd251d6925c3bb87904186fae16c0421144eb98cbf30403ec02f38199a62c41f175d19eea8e3cd6c25897e773005d5bf931b45e2494c7553903bd64f4bbb316a11fba9a3d2ecb3f8fb6dc28a07241ae8a4c755496a494d6b0b9d4205e35a46e028b72c7af11d6190b23a2c70404624fdac2302c509974520bdfde087f3649a241967c9afcc16970af251b5ab3046cf217312ff0ad54f6f23ba940840a340498a257dbec3ffa44532057fc2e4e12a36dfd88e7ec42a3885a6684568af0b8e821b17abe98f069b27dcc045e8fc2403cf1e764d1adc4aad6547139d107f8b77d89f1aaa2d3be24cf480c9e03019c151c173015cb1db490850fae6be852af08df73ae2b98f763444d28408469ef1104f7816257a27a7cf78708dc1e310bc0f7cde56ba7f32def255064fe81e9d78490ec9479b9acf7328678ca8aa3a8008902a9fbc954d8c1ce50aecc797943d3b1ac681548144cbbad4805773408f2c2455f041e68ef7ed757b504981a38610f678464075e662a156c058e58a6c9fca1c5c352dadaa66041bf074036bc3258df98794dcdc64248a4af53cab90d7873b1bfa2dedaf6eed93a594ead4ef4a1f4e843bfff325aa756942b2851a9a526f812158c591f041a8c5240d19603bff6afb53fe8d6d17a69b5f0752e2e7350cda72baf17d77fd96e1a6c5376c358f61cfe5f484bc401aad80a44a8082305bec47fe643f782cdad0f8c1b46b9e0243a66498942ea5cb749ddac0f14c13dd03cfafa9840cea8f012f68c5787e7a48fafbc8c670a564341dee0331387e3efb7864a56b3982012da04abc3348e46eacc521dc9ec86c6a737421d5e7cdaf957137a427efba3a0837cbfd17919c93108ad6ea479a7b41a294e4ceb8b68585ee6bccdf500a504867094a4a40b20d254ac12ebdc0f9952b20d582dc737c5f7435b6de29c5bb73da4b55ebbfe1bb7e0a4aee4c1af9d1781013e082484665964eb913f2fb8c547096e8a7a0cb6b8600530c4824c0b7b61ce65f1f4c04905aeffd6ef705859b19ffa28e88c65d1080c61e6f14f769900bcc66ead17e7f8a6bbb494efd4141f7e158a5f6924646ff7019ff67c0ed0e178e9dd47f53c6585887afec69c41fb40a23713d889141a0ff48e84778b1e6f1112be5c80a6272d77f514af6bc9dd47bc6d85f0d7cc166c20c2b8255c2fb63c4a9a303396592cf43a8de7aba3ec7a0e45470410d8bcd2a01016a326617bbff7e110b18129a56900515a8d54224467773a7a731f28e9bf5a4bbe640ca5aa012f1b4ab22fe14f121f3a486505d01e27b19a87801efa6fed57a636880dafc40a820c73ea49c2870f34bed3b504c2f61d1a61d073957dc0dbd97b2c68dab42d9e48bfe559643776004d2fe5f7c0c7e7e843628ffb368dbc65d7579a826932bddba17db9de0f3e573916f2e80bfe65f1be24aa0370aa1fb9b84a140c3d6f62fe116a88528aad07d190fdafefa49b10c4bad1ecdd2e6168310c346e0143f57099cc9ac8159e003e95158cef5a518195e8e53682e09bbf1d259dced3aeb19b3ed9089be1bf50ff25080cb7be32e64ea027a54ba01811b9fdad60afedbb7423a2d958b90f1a568c413e50284cba2ed180d3df64a13f210a824dd309871843ba5a5df8dc016092a716bcaa39e59c74961bafcad934fbfa1ac73d8e876afb160c98f7ddd27139b5cd3493cd18e08290e7869e203e7e3c5e2a077219dacb8838d3be44fcde42ea5a3e4f21037f1f0f66ad8b526d723c31b037c4c660171cbac2aafefba2afb0cf667bab8936a9453e6221c71956ec22cd70ad54226be512911597add00b3847347505e4e7a412854463444cb66f71eb359d4258c2fd33c5532e4fff22ede008ab72fee788e4bc10c4dbe9dc3172d6406f6b829903d6268206fd0b10bffdbe1fd62895790dc2f0bbe10ccf084605e3d19d4a86b4b64bfe62d3e7a1f43afcfbbaa5ba55348661d4c416c7219be1de32d038db26b8cd1e947fcde7e3a819e89891df896490996cbf958dbd4bbc5b82bb07ed2b83c96a87348fce5ac03f5e4ffb987c02675a80465ba54add3ae26f67da4a53ee326499a44031defa232cb152a40450ebf9fd2fe39f6c18b27142045bf53e844535339b0ee3e1602e499bc4731e8e536eee46d7565be292d2cac2586c2ac0e139ec733f2b240fdc69dddee8054fd0eebaf8df2d9d36f15179c0d05cc309142ab8d30a75a613053a21c5a4d9e1dbfc7ac0ca37168b999646711a61e29327ef73f462be930228f97e563e6b1db0ad480d3d73f0492131f2dbd94a5b3fbb9d2194adfc1a396e60bc2d27b51289d491428219eecc092f56250debbca32182a31fc7ea67163c9ab89191505be15f3abf1fb397ba6e540cdfb3661693b6eb76b4da66e7d9f887d7b415ed946df1b593e0523b41f20cb1edaafeb53d733ef11e0cc0e2eea5a8d4497c82f1c5a3bfa39e0e9d49b3acf3915fa69e4b9ef7b69a7f0825131e6587d335ca66c23d4e54db4075d61ad0e6171711b94e1b647e62a8b9c63c089b0c2f3bd9addf550df187a1b9d7f122278c697b91091d0bbd8da14d3ce2627e5076556cc54d3084c447aacc82f2f667f96ffcb41fc11f5306d2e096825f257f86d55289cde430b07afcf2f8b8123489ef36e58beb4bb7af07da8bfe6dc9c2bfd0a2855848dd46b70244b7d2023fed10a332ffbfe1402ed48e30ea1b3f45ec88d09473ece65064b4e15e62ef959745ebff674e9ea0f337518814d3e9d7aa1c240677dab91b9c0e41e40cdaa5531799f3d240b7dbe702b84e88688bffc56bcd55c6d3d4f936ebdca448add1c8c84c54cbc7412fe201d76294711cd5349007b027fc52d91acf51359dc68e30bf80162450b2e2334dbfc653636ae67070ae6cb23a8fbdbe8f5df9d5d88cae4d515ae6997b22d2ee3eddf2c7ded6ba7ee30ecebbbf8cea56f0ace385b3b4b533f99cfd7f2930783557629bbbcf03f54b5685ef612f4c15f9cfbc3105355214632718898c829133fe2d69ae468cae0a6215d531f4cc801fffd416ab86c4823c8220059bbdccbb945aa7edb32d8627f1f94299e36448a30e0aedad92bef31c17767783b16c818e2d005621b2a551591249ba28005137d81bdcd637dd98169bb6a849ca57a439e726f5ff61001c949c73b5b2b76c1789e59c64c739a6b10ab7fd3af7be25c45d194dd5a961911dd628ab447999b84863b98f53d6b06733c2144549af2e28d1dffab2c147785eda415caf4e9aceac3a018a97f45c2bdfdf84930ea0ed5e5b5e55e328cb44217d89dc5b8592e9f82d2e9eaa43349bd1b82548efb44adb3cf8992de1ddb0389bd7074b0696ac25828dbe1eaa0a1e46e60dfb6b92db42429c01d7f7829e2732cc0136503d4bea76fb98554e17aea5fdc346c7d457ea65f128ca37846e8fb72de28a05079ae802ecf48195840e2a7aa935d817f0bc8d38c4c283f25f3d8b4a92eb7d48ea676cc5109b5cbd651e047ce44238171be96141fd30968e4d71e3ffe7299ae7ec87192ba819d27ff91781ce58835881c941daf943d675d486f6353e7b067becf2ea8d71d08b2aededd6f1045975c74f8840dedb352255fea9f9220b31b1f677a4f7ca415bfcaf3451b49fc7f3c57267119b36ff60e618a70423808f87c7ba2e511b4bdf37ea80c4024aee17953165127a16e88d1f745db529a048175497421716bda17f4af5f28be9d0a5932628aa6ea433202d6dfcb49941d9108ea1b2cd0b4f5d274f35d52bb44a8703651e0f0cecfc7fe933fa5e0dfde92cfadd2c4e7766fbd3a9f214bbaabe2a27c1ddd16e563b9d7539d7c793d00a52e2aa1ada1be432d41defdf6cb4cd4393266dd3211309f37dee5f31430dda1e9346217d94bab66b41f44a93cbd7bd10c94906fc95a1f533f03db5b4b241c7c388f6fc2cb1d455bb5f46017e07468fa7ccf48e1a6763e8d8330528439501419214353676a96a4d405424892c8cc19346f71ecf1fb0d2a2b348395abcf044d64666989b5fd03233978cef4f80000000000000000000a10171f272e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 29, - "comment": "signature that takes 9 iteration(s)", - "msg": "0a00000000000000000000000000000000000000000000000000000000000000", - "sig": "bc143b5f4bf58441c91faf8a0f173603ffbebdf13ad89694b29fd3b6818b273e3f54ea9cd7dba3d4510ae2c8f14d843348820d2de5708d79984d05f5496af374477027560edb4795d84b2fed1495d55a1d1f42de240136a7596889a5c03a19a7659f39f9dfd9cfb86fc6e96182b262a94b315a627634ce2fa57f3c1c609bd5bbe27b735e13e133e14acdd1e177ba97bc48873a11ad3f5c49c7a7fe1af5fa10e5dc50c89c387a8982fcf562b2f36af26d05e05680f039d422ef9aa86a5a1193ce24bb88b4b7fcd12440873867fb572cc160008902f9163a4c238396ff943c99505a7b73ceef7fce692be774a3bb5e04dc82df86ea15854f526a2619ab59117d5faba3a2c4acaf2d2d8dc1c5a13affc788e561b1b0923ae96b139e4b3bb55e134f6c2d0a5f8f25fd37ce52ded270d318808c6df359185dcf554a7cd8e1b6afca029c5611f314dfea7e008b1640bc57fbe4a0f69aadb51bbc52a94eb20a7e494db577c04c33c570afe493b52ac0d49702256bf1d948b23e0fa01728a0d7699ce65a2ec8f51c94a452a10f2033b5d6de6184e3fdd07df3fba52836ced06955660ebce4906674ae4dcb5d32f33e87e5889bef909126ff24a9b4b7d51455c19424591c1ebd20f608022236f42d06e90d4cc5e98819fb93fc1b53b8f0f374013271b59ad216bee3101e217a15a58b2f59ca2fdf72dd039c76b5995226a198904ba1fdcfe2685074c07aa60748564cea870bc16f13afc6ae17363b625d0d5b95316a0cd3c4b5d9a5578e57f240c6f8e38ce0de11393c7a2f86b35e50fc19933967b7f51c066b98e88235d459c54d4d1a28d7d194964ce1449081affed934c99854f7092e8c7a6b5b6987d50c1e2dfc4c8b69532b9322c7094c56776ef509030539ed74e991db7fb14b5f676aa7306a0e67d38ad8639971471b578b3b40f35b4ed6d4996de86cd634b1f63948c1a68f056516984e417ea2e1815428a14bd153424445d1f32567a0432fb06a33ac65b861c89aa2f2b79fd911c2a79887465f3ee2220620bffe347bd21d57a25f9e6c97fc7f00c4570a26a9f013624af4d3e24e34d42dbe0fa6c8ab7a85cd735489dab9ac23a1e5fedb11f4c5a98646841bef52f894ba45245442febfd60a66af764efdc16925cdf6449543b49bfe34d3d5dd51fa242e9dbd7ce9082169e56217bb8501947c0d8a4b41f12a56ea30a071d2c6cd358ef952b4f18f417f324331c500e7c056a2d47d0e4dec4e892a0b3b3773bf74ef9769e7d42815af6499a7263719da39a88fd74348af4f53385d76ff0caa71c84d5561b9eecb27e74cd20c46104fe2fd0f86fea87f83ed0213c350d0e16c4e6d8c973c0ff0918e14ca27b97b19a3ca0767f0c213613febbccbca507b0a17b2bd2f042b8509f6c8c38c38842c6dd61cc5cb6772b23307cc4c400f4a43d9c644f448d85abd0b2740c0127002c6da081067d29bcfc1ce1aef5a7e375331b5b9c9ccb8ce74c179ffbb3476b102bcea3e33f947bff12f5c1d1f95df11e5c06f123f23083b7ea655d135b804540ba7a12cf4f23a0c28743289c37b6684b5d357f7a0871ba5f10047309cc4dbea769da1dd0c24db4f68de2c811aa3e2b0c36013daf6b801ded4aac4d83572f4e28f3e360b1e4da0ce26cb98e79981231d2ab7b3eaec655c3cc5e746e7d89b7790ac7aa29404d004a8bee6e758ca9759d272ef565878bdce47c3fe89060450525f5914778553f277227c3bd6f970107ce3b03d12821d09bc7850305446d42665244e3121407f8193ea379c322e0e3ccda4f8c24a1a8cba43c25f27fcbedf24c62afce4e143fd76802cf1bec1e2411c740a111498e2e999a54149509ba83b3d3703e576aad701257df6b969e57c58e4c8ae0e5af4ffd347454a0d101ef50146e565f6fec8e4309225c2ee39c4e0e29027eea6f5cde089a56067262bb297880aea34423fcc1ba816b06ee2bf9bd4732691b80dfdacb015bf005a7a74a486b6cf19d5dea2c2621ddd19bd834dfddd97af99002ea1dff190471a6675b61454408795af44266f438d4f94ef8ca8331755fd9ff4a5dcd03e88661b2033ba3e615edb7b061cb6a2196bf41cbfd4061a2580b5df7a4064ed173810e0d35181b5c324476fd99275d2b9384ee0d40c1cd399c2078ce1f5b622b67ab424da06f5e746b1e8cf7ae8b90244b0dd637de6799cc35910b97dd03ba01521dd9a29cb998803fddb4c680308597095f202631323e00fb85fd939494ad59e34077f1af3caf085ac82043de604c9fdf851bfd162ac152e70f1dc5749a6d8ac0f55880117218a8e09e3bd6e2e2c050fadc9352305ea51d9e6cc073cceab1c2369f0279449564bcdd7fd686c57a2123bea9735d89ba4b25614a20609f6bfee14fd03786fa0930b04e7567dbfb51c408842f82e658064a1253027afea7d4d825d1ad60caf8596c641a3cec52874eef424e63e107863abafbd0500fa0e620dc6fd397d42c541536dece5936a556feb4b8563747008496e4a9d5bb1267533c0b9ef60737ba9d4a0f6e7b2016a57311ae854e55b144412f085c647d747e631acaffdf97410c693d089fdf227ab8ae0318636235f189278e0823eb68db6801ac6c606fea32905d000ef30b1489d6f4d0124d10b97b12f4db0726b7374f8a5951cae97cbe1e30209032b9cadac407cb474fdecd6fbab06b5da028e04e0dd77172239f41ce56a3876d4c56bfb5f8ccf5d819302151187674ef477eea1451a6e4d09371358995c552b467bb216e88ecf78c78c6a3ff4c455c7689c3784d4fdd50ae4250110e39ceb0c2a04e04a3abc1a2ae95ad9011bf2364443ec7773a596970b16d7514a0a7c27bbb0f2436bcf27202ef21543ab1eb1314fef197ee50b4bacc3d8f64bb9a32936e20e0c0826d1af1500c11e704d951824fa0a0d44caf8055f5bf06e8e0ef2f0617875b2d44a3fba8006aaaec6abea7f626f90b5fcd1e44bc2401e0a486a8b6c2f96d76117e70186dfdcc10a677de2888758c6af53bda8912374bfa25bb48bc8d8281970b38bbe2c536f39874347c91b3193531c456974e02393d35dd57596f540ed9ebefc87af562cdf653eb41dc5ca999ae1cf0ad9a2ee47c9f641b68fc56e289844f5f17dc94e3acf4987b33bfd36b1844c43fd2f0fe91de2283dbbd0dfc1ed98cc8445c768a1c25835b9d6ced33d5defb877a7592a7182dd29f5275b0ae7de9954fc000daab005d3289c1d183840cac1832b0a13b4dd5e3f0ec39ef60842fee868e44b946809f8a1879c5a6ce3820b1a71aa6fe12fd19a79376c5246878b000b89aa0b010b449a080a901a24fb8ca8a92c5c2d9d52bc27c56505202f7e7964c04fb22bd6a8812c2bb759ca10f52402233ca15329bd9ea9ec76129f884355bb677470155d3a866727ab923316f271724ccacc23328a07b327835cdba5699f6dd4e29d80d45efc6708f8b7b17d20dab0c0c074e595a1c2565cb98a47c589ad761ab30d4b46c97a1a4d52855f8bfdb2fa59b63778c7b6676c0ef5acacb7155a1362dd2ab49caf6d95b676529da71b2bf6601e7fbadabeeb5827f782fcc80f8325142eb172660d2e5854c21876f1c40d93042b1b2b6e0e5cf2ccdb6f2cd7264ed7c106fdbe63fdd2d130dc242f1e71f5f9b7647dc2feaaa6162b6fe0cb3825136ffaad90b67bb67d2917e657bb8a623a5f550270072d95219ace90168bebecffd3733402fad12f31fc9894ac6bcb51ce94bb88ecbd5b66bb8ed88d2260523e21e4f6fd20d8db7df6c2604e0a659503426ec9b167a884f277a9860481afbecb69b2c8ade9c270d5f6d064b4e6c95e63d6a20e06f59ef800d07261906ea6541e77af7128f4fb3e6ec5932a46b1d1e0580d68896d256f29baa055ed91bd177cf1b1ae2f386382ad95c1da7d7949d398b6ded44859b9b4af1a117ca76cda1399a1def5085111d69fedea3fda8947c0ea3fa744755123418f127fb2bf57eb04e9480b1e20bbf9a091cd9830ef6aa6589df921d498a149096b1637ae5222c9481a826f34d5c5e66dcc2a977fbf141814c274fb2c07b6abbb973456354ed4de863c3a74dc1ea7007890129a9ee6ac41c026bbe9faea3ae9b1f1bc38fec4924b805143c0734776eded25925ab85aa943d628f17d5c4cf37e41197d1dacfcc1114eeedfa449fedd5749de33cf83add605c9d0bd3e32ebec64102b706961a40ebd9381128bb2b430748b5b62640a065cc0874d0092a4660bf00978b563257aaa4fd9e210549b5262510e695f5987369588eec3f6d0ee034a68ecb25eac0f0d9764fe27819d4039af013727252808a6c2507e2da48403efdc9fb1b27ab8b1de11a4b372b2311a939f3f08b16c77bdf15f3ec5a4a916a179ea7f64b94ab37bba8b8ad8cdd03b3a4e929f832dc0ddae5ec0bda1975ffa2f5d89c060b77c88ae263c3e5d0a157c3b2102275612cbe3d26a0917b525fcb759b958d3682550da4d9cb46d8787215d374c126db9da46bca02cc4742bc5ad984718477678b3c1201afd2c94245fb4a591593f38caa53b476c9af0784e999a50e62954fd2fb6bf5536c74a7a9877d9e20598977c9d400ad84cba1899f706d65666060f991f3483a2cbf8fd1294a7b5c7dfee0338414b7c7d8f969bb4ccdee8f205172e30c83249787ceb2030375b7588d1f0fd0000000000000000070e1c21262f", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 30, - "comment": "signature that takes 10 iteration(s)", - "msg": "0b00000000000000000000000000000000000000000000000000000000000000", - "sig": "d54fc0ae94872d53a8ec295b549a9754c675028a84f54c25695a3acb715e1a3d8ba9778b3ddaad25b8c487d21fdc62b879f43dd429dac7f5c303a485d0cbbe1e9f65e53ca8f722cad42c27392f63cda0cf5569930deb75d02bbdd3f971f6a9ec96aaeaee32be48c9fdb4969667744489b349bf480ea1249cd516ade4d4b581e3c41103b5267ba72b8dfdba0e4621a93edc18b37fedc35878d6f2bd2d0115cd5c2e243ba4aa02b95ffe6d3ef1f12801ff1ec09115d4255e202d957d0b8666b60dc8767b11f11b311d9d1f0c99f67167025ac9a0ed6c77c319a5d261ca5416699bb51c961d3a077c51949091e6cf0d4cd261224b6a88158d78a45730b6a86b4ca31380540d3d04228cd51c00a6671fc0036b657f3b52bea56ab503adbf4fad1e452bd3b1b29f27ba1e24d6f302ea788a7e59435ede2de69ab30e356dbf17bbbfe176c2182f870ad9a8a819f5b85587d229beb13fc6d4034722b72de83c1613fe434dcdd26c0346571cceb396e3389d08e1094fe069219a509e59ea17381575f4ab1b4ac79cb6cc64e5dc5897645631e187cb4f4ebbf1dffb083f7dea6bf6b4991a32dfdddfa43910bb526b84c797495df6176cd7e5ee6f42ebf6bcc28fa9fe396a8f72668d33db7821ab5ce54b7930dc7a90b97b9dd6b12f5d370bde4ad41955c5d7c1871632fa717237d4f39dedaa0cc4ed74900c688ae91571fa717d5c8f70837b8c27b26bb604ad340c98dd5d1878ce286b1fe4451a20a88a4e8902e3a1cf10268d26dc6446f7ec48a84b8bed9641004e1af82b679cf1bc29c7f9126f8aac9688ead72e14c4fb18292ca507c976408603bde8ca2650e3e50043ee112714692f871ad28305122149f098535424e4f278730c0be7c1124890cdd4260dc32d63db460399f9eebd339b73a738b58c0a008c857853f0df76789428213f65107c4359038fcfb366fb8cd74f2d955e6f2b30b3e96c70d9100c781f1d6031e210b541c4eeaf30bbcb16ac3c7b21cf1093fde4999c8fc254eca328dbbff7c5c880beb3e295d2924f7763720d5ffda0cce07e8889e556edf40e681e6894fbfc49413fd5b3ff232ac029579ef7f7cf60bd6ccd48d9f76263e948049a217f12453db900ad213e7f3e4fc409710fee4c92cbaea422e755cf51505730298decb37d805d1d333ed46a84e3c7659f187a344f5090bf338bcc76aadaa1e77f726b2b11880ef162f5d2812890a0dfd7b9a21f294bf18f6b447d1dfd92d009fbf144fbedf86e1cab012ace0a2ab31401c5f8f8aca4dc92c3609fc263cfcf56ef858446d9c66383efed916ca0c0ca351b539a7b4110658ba425d35b4c2cd1e235ff2c1c0840a292f23e34ca7121273ecac5ba01715f4b0d35bffec379da93405994ea997209efb895496eefacdfe9161f7c69afe3cfb9fbb3b68e105edbb0b27b1d0514c47d8886d58dc00c6cc20612630b0acea51396ab086c346c07206888257b9af5ccc06b867ceece53b4ebba63cd4a374503a524672527ff66f570dac73094f90c6dbd8fdca572a9388d243f63521c681ad8ea17ccbdb4b1bb215acdbae279ae5ae1908bae519d7398c7418cd56d0804eba259ac01a11789d538d848b76afaf7b93fce336b5bdee63d23b3cd6c46dec665af77a8c4efaeb9e0ee1576fdf7aef9807b4884f767d6c3e14c99c14c726c686ba8feecfd54c14a5234d7ce4ad7093c673d1251b353edd080e30aae264037c61ba8540640aa38101f73ae91d788a534511314b0cc0b4c52911032bcd286919ec56507fee54032f79cc1e1d6cc6c88d9a06215e9f3ba38d5f7bc91781e8cd863108300db6adebb51a790f7a2ebbd8fb116596716b1c7028c8cd9c1fb1db566c1641dc732d41d75fc7b8b0151d1daa407fbd0aecfc0fc484b1d43f68ec4614a32a38864d4acef274c6ebd8c8a6450a29d4e63503af63db37d22aced927a24dc40870ea3a891045a5a77c906b963980f58c5ed754ba710257fadd4f50cc13825a69e3548be0f5e10f6322137943e44de4a5b3f48d62ac256d7309e942dd1f3f211c3b8e745f79984dd25cb9c6650fd5c7ccc6e222852d8160fc8c97b52bef915407e17c88cce2eb560d359a92092846bde8f36f5b1894a3e69efff64fca4d6c0c3259aeb556370328a3eea80c1b2e61ba1f9ac0c5bb047a4084aa0668103a51ab97381bfa7e6a6b631e71a91d6191c6983d6698efea65cde4a23dedfca7e6b9a329b132c3865308d7ee89bb49de4bedf2f1b09dbbf729c1f0c53409feed48a120d2cdf57301974cb05e78619c848ded1fe6fe493dfcb581d5bda8ff0146508ab2d0caaef2fb1163bdda0f57da71805e6e53c8cc56a33d3bac12250ba331f380f090d8fd9c29c94935a685d6ca3567f140ca4278970ca42eab4c75056700bad477ff9865462dd82f7bf05dd0b4acf59b238a9bc9566997de3e3ffcb1778d7817b7196e3d1e06efb4c6f907006837c8a2e5117931a3921965db84f51390bf48ce8b54d44c6d8af12dbb6d171d50145178822fb457baa2b78246540fd9a348fd3667fafe1c4b983665d2bd676dab43a63821bcdad0896723b7b6c33e78eb9dd7823e48e028197cf494b16ac3fe0ae9978b369ae4f144c7aa3dcb5f2263cd2a29dabb0b14a442d804fadd786870565b40874982fe9a1f1338d1c02e286ceb42ba0461a73bda8e2e1304dbb98974f7dacec8d90d6385cfef3f453dbd098647eca6d33e028fd6c0279a090e36a068871a1ac16e298aabc64d4e7d66f3e6fcf74f56ec909d8aacf8db5d9af2185fdfe2de96ee568f78f94910be75ddcbe9b06dd7dc290e7b7e162bafb6a3cf8b6c90a8b02e417b40b632d7c0875e37ebbfbe21f2b60535b2fa76c3b1cadbfb8d4176dcb13b530e660bb2340f276d3be55ff24b29746070bde345fe7bb8d06b7a4dfb85336acec4bd02c95b8819b81d1611c2a61b31f185d70653011f7affa1f6dadb8ac5e832659e09f71322a60770ab18c3bf2033da08fc6bcea35c4f3d00b36d9beb7e5baeb7dd63ebce5bb46b600be9fb7674fc4788d72f7a98bbcdb23c49dc6d75d7223dba5064cc5426c781ecc73fc08a975039558ff2041278116ba8a477c9da4b4d9a19433de8709eed7c18a2bec23aa6c2b20a6cfe1e36e27bb4f4c2b0fb74baa624d3e61715aa9f0188c45d4405ddfb4d31af661defb888150116639156a92316f1d77df1c3f25055e5ecab769531bdeb1f5e75bfef8e0b521fa6df84ff2d30544867bd556e054a85660b8515c82884c46f8f6bba9e7b1bcd7ff6858d97d219acae3328daf5018eb671965e8bfdcd1660785e0377a72173cb26c6db4394a7565a91e119ea0ed09f549edf01e9bdab543da2b1372f977cf7402735b5646514627c2fad38370e10ba0271390cf987e6fbe28770961cdf51d863899cc6ca6730788815496ce52e80ccb7a8e4a4b26642db8d652cf4db330b92ac6d96e7d357432dcf15fd831fd3ae65c57dac7e4ea822a6f24744c2512127fe386b9caef4a82f75694779a950bc33c2e86d50efe6254345793458b5f3089df8a9b21268c5d4031fbf095afde2d9f5d7f8e79df08ccd2e6c892051ceaebd82fc3047a38e6ea4fd6372d3724af26031b5cf9ad7529f89bc45b68a25d56267dd55cc4b768159919ee83210cb0c2a967fdf9bacbdf8b91a2adea2c51d73712c8dd051f17c6bf74a0d1607ea48cba029811a24101cfbf6c3951e112d39acb3522f3a38066f048a0ad2996f846258a3d136831619f598b408cb6db93d4f2abc1875eafbc778623ae0f9750995372527397f3d427d1a81316b448ad9d82169ea3873a0b06294981a604574256e9408770e2e6cb4c0fe67931f015d6b844bdef6f703ee80b62517fb81f9c81a20daadd9988f912578c5ae932899949256f09a26dbd44eeadf93a708ffff3d6edd1aa55bd7e681564f4b183176561437ae8685be77acc1878ce9da23b280c1b5b46dc34c4bbab39a5969dbda6793248e0e2efcb56ffcffcc40332cc54924f042ec3a5008b1ed0db81bb1d7af47e110243bf388bd75af256be280f3fc9486fd3db45b9769420c159fd593eaf4b507a038760e72e65c766a120c9925c4cc4880518ca1f810b52c326e46dc489f694e6f68b13ffb669ce5a1bb399bc9d25bd5d98c2842e12a0ed9108ba5136b865d819b1c0c8fa020d3096935b78c832abdc1ad1b22bbc80e10843ea4fa9412002133f5a5d825f86803cc699e42521a6249b7a5a8742b9b214e6557c84609b1fed79893ee97fae0172626a9f00ca2d5f7a7314ada0037ccdb73a294db5235edcd6e5ff7752794c358494a9c1bcd35046cccd6e883cfe07a47f42a9e8857bcbb0d89a388a55553d4dd120b3d30d6ba29192f76812a21209984f4d288355eac8a5f9513e28994ad8780b3cac76eff15b5e0f4113d1ec4ccb20392c282e14dd52d370369eba9eafe0175ffafbdbf72cf9b99afb23ed2e9a52a96db144837e0b83d31c35518c0becb701c8b79ab7acfe308262028f00cc9bab4cf905edaecf060c77756a0d56625b52e26ca4f177897abafc4e730d8a2636ad2b065bf32bc17c954f08868c1d8a8a804e5e00b3a0759a174675a1a9c1cfd0fe052d4a537592c9e7edf3f7fa1f253966a6ce104a65696ab3b6bf0c26727576ef4a79aeb00000000000000000000009151b23292d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 31, - "comment": "signature that takes 11 iteration(s)", - "msg": "0200000000000000000000000000000000000000000000000000000000000000", - "sig": "b4ecfd11224c059a2731e7232dda71f943490c5d84a218d2cb00a6bf8f96746497b327d54ef0528952171868270aa6cda099a943123ecead4d61138a5a2bb90380865ba0caeb5fe3a4eca46bc8da8dd6c41c5294f3fddd7aa138e1386f8f833c7271838853873a61912813171b0003578a8db71536a98eff4900a138a1848cc45475fcdc2295fa322b21d054791db116b6cb123fba5d51ed4c133985ced556e20590b102a53567c84cf41bc68102164ece90b87744aa46dd6c84c67ef69a87f34093ae127de228416ca5c795ad3c4ba56097119e6085073e736f0dc4cd51c4877d022650f911c7194aee9ff7f13f94c5f73b0886b889ccea790cd13c6f4c52effbad4c4ab89dbfa816b3ee6bc1e84e3b4d948713df5a3baa2ba4a2fb8d9978cba124d214b251a1594f956c5f175d3a5122ea270a085d11f133810f7ac6b07c51b13f02a590f39b50b85c2757eaadbfa802dbba616c1b1077f15644f1e773fbeab05111834df770e31a460d430867f3f0a1e4a77951f54aaa1b04409dc75c6e4e56063a531c30f2e4529f201a641a2a7b682f6d26e9f18067f16b0d619cd7ad06874e4c5ac7f7f508598bcb044486ef50c1b075f8f879e8c7ac93481f4534e6c982ebf9b16f0f83c94504e68ad99c187d2aace43e1c4726817e156e2ae2c6551f9a2285ccd5608c131390058cdf292e6619f7405e68453842d8e12c08d8f0cbee7b25bb4841a9afd520a4a25f92d00fd65852a0f03bcb70c49d2f95cc06f64312fae537bfd4787def2b3c321f576cda847eb14666cfffe2cc61c35139c88a308d54ea4f7500fa1f1b69abbd50e85f6baf0374cdecafecbbed52ab0d9d72ea79931d78d8c86652ebbd30dea1ad90eee7ab63033f4e0efd14622e5e9426adc9fd40847549c304535a5eb562b89b38a2d40d2173bae8cdcf5f3a049c3720db29967c65af8485d12dac3240c803b128fd89eca7f9afe3e994894c4c6112168cc89db5c924de54b346146a917b0427ca196eb5b9668fe698f678f24c4d612092ba8f7bf26475838dc52e2daf146ebd915f896741864b01f7730d02b97b3ad58eb224148c33c016fbbdf1435e3e8b842f2d42d4d427f0543f4294069394c884669a87d9041001413d257e5cd81354926399361196f40852940ca48a4bb74ccf812883eb19a4b404ceaf245b83eebf8f47ac6b0d00237261522c6166438018ad900f6db322d1bf8efd6ef63a0065a1366d93885b2d1c1a13fa37d17419a9f6ff878b720001c1bb16685f8b5932b75d734d3194b9eb39756a7780cce344be03fe5655987d0bea11d0a00e526c7eb479632a4db51d056ad351ad37f51dc14780b4730662b90aaf44ab5f2e305685c641411dd2b400baa21b2b44d723ed7af3ca3758b850675df9ef5bd1707e90ca1c6fd462b6d000668dd625023bbef9a6c244d27557afe307382cfbda0ff068fd228b863164ded33ea50a16872e759302dc44b4f3538a7dcc8bd0f82385a79effa8cf7db60d09bf8a349dce50bad2789cb1829a6624feca1d15505c5f37aa8e3f08ae1ae2ab8274498546b2931c2a823427c2c5200bb74739953a18b9cb96adf21493d4784e08aa0318066ff0b75ab9427b21212be4f09c3413c9c84bd704537c850e30fb12bdd862ccb1dbd1c31373ab9dec930100a07b32d6c6b14afe50e5b5b8fd2d37a90a443e3cd2761e31800cb16e31dcab74c76323a0f462ce7f7320b75ee4c21e0f0306c67a8f69201454c38a466f183431b155080860c641adeca00260567dc73d5065e1acbc055351c2eafc1121697cff2fda1eab331ed6a3908cb10ce16ca8fc6179177e23f9088f17232425b59180542056b8ea61d7ec0e58d8938fd205fa62d7693143d6f0abbc6cb4f41cdbf44dd67f5d7a21d7a0b7536df2a4609f644a7f8d96b861e9e853bb2c9dd828c73146f1e9e20b46a067e48b1f3694cfc44a256b3bd97801d748ec4de0b3f8ba52bc2a8bda92d79618045ee5ceb20b756421dc92747813aa625839b3578732f2ad1d801935718df8d5e83edfc3c23e5a5e15d4684c42d3ebfa42d013aeff74c4ed05f8ef5143409a9e1c1d8f61baf5c9d0e3b072be3aae7ab9c2317f2786d39b108b12d948a0373634e7cbeda1b35fe9ce694a825d6ad5d83743df1e4e4537ef7fedd3b312d56c0754426f23a865dd667e6896a82e6062a1f5b6c8a60d08377d42ec5b43c534e634d9d85f82b913ca10922cd6dbd2c3d7d35ecc98cb37af974a615831846dfe9aacf9f801ca6cbc4290bf5e8d6bb832df0dcbeb93025baa2ebd7f3b4941e617d5437fea49d5f64d78c2e2b422bfad3efbc4bd2572cf6559cfb7001e4886959ece69b5305f0799cbb871b540df18c5c1935ddfbe17c491b9e1e82c2c9a1fee6879617463f60effdaefb51bfe749ee3fc2905a3a9026e087c984276a543cc3f4e7a6948c8d92985d24edde89b36ee6d9b3d7e300936548c34436389f4e7bd055f26a856ef9cc56de2733cde47fbd173a9874b73d0b8ac3a9a09502c2dcc18585810916a4ba6a72bfe94bae53767e55495207c2989d77e0e0f07e707f66a1efdb93c8e149839ce72b31b4e17d616ae0a674cb349c2d9fbb5c72b833e7b7916246c8ce495b3e1d7b199ac085dadfddb2bda88c8529474f245797d7756251344305891b098c711dd6a74d54036b299ae35bee1fe7284c9ec11bd8dea6b8238690bc40648036d56401f26b92584f726de2445030cc9865545447abec4b4e2c0c06681ec5ec0243d845f35dfa8d80127fc2542cc04cff53842e977a3e9420e6f3303f5d1c11d7d09c15fb229d0d432857987d6ee4440be1509321511b8cf88aed7cb27c1d745b672492d183815de62f1d8f69c8581d7e6918f13225f215f313585aa597a3c8876ee67317c0ca184bee5fdcf08ebcbf43d01b0049af2455bad78bc8c28f11252bceec019032e4feae4ed2c5d0670f9c2b6d5ee96055469c25661fbc8c09e1a486013b46cfb0c0eb4774dfb65b8e3688a02cab987923a98e7f75b44261d44c4bea44a0df4ec2b8186079f3557bae7c951009a64cd6bab08410df3f4ec65b58bfb8e31c3659d1f4b3254386d850385eb8cdc19df92f011d86ce13ee526bc524bcb465ef1aeb8f08e809273034be71d95064979ac196d9c53fbac31789ddc3b3eae14d2c1e1730e2f5b38fbc352759c1f573ae742c6cc2b15fe41fe6292f3856c328814f7d70343d3320aa754f162e530e666889fd0187a65c48b42bc2cc87e79d17102cbf66d8564ae5fc71b92ca49b04d1705394ff1e6af4593792d1a6ca5b00e972180857af83d289f6d0aac81e2006eb40a8d790c7dea7e075404e5e28293f4385edac77094f2e2dec38a15b12894787bbef906d12f8bb4657c7e3e2c8767a310277f63cda040bdc68c5340caa2b39b7579873cbd593cd81532e628ebbfdd8794b4fdf82d6c6b20d7f6bf157096a96a5d327a972faa5cab92c442e468cbd6705fc8ee489489cc687777377f87b470a84209e24e18150076a1a462a9572fe037b8a69153d1b7a41b440cdcca5a2d7b4d224bca60c7184828eb519e77f2c98b4567f23251bd3d01d3ecbe70eaead160681053b4a733898d74206bdc25eb6fcec2a65d6a972c680e0aaaa1e8b1e3ff095978213d242c6af612a62dbb58425037cba5209588ccd3c11962ad47a9c4455b98a626f92264a0527a28bda7f47e804ccb393caa2590b957e5fe3527c0d5aa2ae7d931fbdd2ebad07cb69be0d5179eb6c1343b3bd4448cfbca6ffa1597678f0bf6e9d2f81f4d6e3a8a9d8c9686826c86415ca025dcd1fa1a5dcb3ca8df92b2ea76101c484dfb1fc58d35c1386a29e588a6c80538ddd18dc44fe4598627031ed1650789b3d0cc1233775e1d45e97504d33043cb721a6c210d6e4e6b70e4dd9ef000adf591e465e30adf27aaa4d8c255f4523f1dea00e9cf978687870e8b75f05ce4fa8dd6dd692e936dc2d48b410d3b626faf8ab013f7be8910da69ae37d1ad99136c15e0e8f4194942a24ccfd55544ef63e692f1d4e9b621b28fbe8efd22920983167daeca33e0734af9aeb4b77af4cb354cf9489676514198a47d8e6d614a76af5bceac2c32799ce43cc010fd421468f982bea4f56969953766f629e43cb2a0fbf3d095f98257a2b6e3ba76f73415d0d920adf9b21bc102fc53744f661d42a9de6feabe59b2e273733df75be8ac972651818e1a72260bff1098c06c572179f7c5b0c8e5e1c9040baa4dad473f96b71b25d9dc16ae2312683868ea048f85933d844b7f2fb685db40ca89f24231b14249a3872f313c14124ec1e505f14c508ba483e6a4e559c8ec0b3dd7ff0446d14e4fda415ff4031fea1e65de59e5322279112ac4f64664066c4b5bf5a08dc160b6b313496546b679eeb31315500d81504706ae14ba526009a84b7270d9f9ead65398278b6385cc136c69e3e431843439b9a75e8b44678fd38facd65c638a3b1245a78bbbc26b85473a5569c5e6e0d2499d1570203ed563540096bfff6208502b12f107894d767798b5fd5ad7389bf55a6a90733511bf5d6273f570626cbedaf5de00c5f905fc2dce53f0f90d67153492082255889a9ccffc83a1af2d45466e787cd3dbf5f7fc181c2024454c507381babcd8e9152a6590d6f3f5143845565fc9ccd10000000000080b16232a32", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 32, - "comment": "signature that takes 12 iteration(s)", - "msg": "1000000000000000000000000000000000000000000000000000000000000000", - "sig": "5fdae986af0e453c98062fd46d281750ab398c0d9be681f09d8a22793a5fbccaa0982761e89509ed0427f0ec73c8f9b4b905dd1703132646ec472f0908440c2e21e690e58ad56c3c4da022c2459c059e9a97709ff8327785011f0378c8e5c14e3130ebc43b2481b016a23ba76e61c2e0da8bef8b6424eafb1fcbe6c1a984ce767b0dc9c824ca1f9a5e8896734c3bb2e01b02bb18138ec550f343efb45030bbd2d034e859145fcab6cf42d48e8e6fbc3f9626dbfdd42044b86adf6dc6df412f15f51261373eddfa7ae848bfee57878380aae7d75612b0aec5d8e1f4f8809e14bc9b244fa50e5c345decf47c597d3bb0f5f2f0e6bfe3648bf7c4ff841d4861a3faf7cb09bdc97ffa37fe75fbb79784e858f34ecd2caff2ffec7bb53627f63bf4f423a290ac26439b722e859acd4fa61673deb275b50a309c9a1b07c7513d8718eadeead0703e5d4db41618dd23901d1abb77c6a728f5565c911199e056dff8c3c0a8ba7cdd05df179ac37292dd2597e38e17eb2619472cfd4181b2b4aa6bf649757010cc5e67121bdc70454d429a8b42850c1dff199567d700159abd3b485788ee01d71ee7ff163c4557f688fff928c5974f56cbb352ba8b3ad07b7ec3007dcd606b4ab84d42b004cd2204451d40198bbb023bbc9d3891d17080fd7d50e282a715fbe97f787a794d0efaa64db07c373c257b0770fa0fd8011fd15ae4edc1d4fc69187385634a48b7405e6c1a473c5640d5125c80b60fc5e48d86829625195a3fdcf6ed3eaea76a1577845d26244e1dc679fb0386d46851e80b130da1defc0c6797036dcc65ec7e0bb485d1f680cdebef97f2780d20d8d664a90b844e1fbe6e7126d15edfcfd37877f0c07d483287624b38000c5689e77fba19d1be415da83501494b0cfb15962243798f6f415206f77f3105f20e6dd73887e7ce26d06b968f3eca04b6a49ed9c31ae0561cd1418268b8405cac00dac88ba433b98480734bf981c4cd74192fdce032c41ba9836088b9e0acf8dfa97c085cc60ecc75f1f5b91738938c2a19764089ed9d81c315c1d91b7e3b1a6d3beb93893e31ce32f97e8c8b837b26e07b523cd857edaa268ede52e0b44f3e54ab37d45d53079cfc5a58a8c992d683a37e9dada046557adbee8838e10ef464262cb0f59029797b6943b7e6b9e0c7010dac5605d6d581a496780e6e2eac7b07b95abcb6d92acf293cf394140f0fb16302dcf94992438050e84a66c236f21b56a756ed0324977ace2196ff58ae2c8db667b0daa54a2d42a3920d5fb5463cb8d06a2ff730a9f533f7171ff470b8ada56521eeb0b5c150308450c6b3821a071fe079925f62320cadd8da8c180fc8a9daa2c8e17561b21b9fd4e221893ea6553a4e61c1fff9fe8ab25488ad1c0fc3521a4e236df4cf15480df5e2b75d67ae5743fa537fa06575e86117782f912cf14b9c67a461c34632fbef9b1328ac76a8dec3f442541e777241cb9eb39dcc009e87532cad63005e5e93a063a32012fa889b00e9df5a63fc6aa81e1cf8e4d967f8036b59b1341ac3502da9813bcd4401e516b716cc2b5ac04f5e57895e39965a3a022f408d40982b2f9e08324dfcd060130ee5f700946e09254932d85b6a28c7bcd5395936f08ca928325f0273e3c268883366a662ebc9a7f1bcdccd0acb6c454f79d67bad0347d85e5acb01bf3413b6dee73a208a40caa15d6208803e3f9cd708ec17497d7ad77eb3ce50353b5cb2b9ac447ef4d58a9e60837ca7724629f32dd894a3ffc3d1e7adc206b385b82ea0bb478f1ed7f675177787f92f1aecaaa2255ab5b48a4f60d2691ec774d3caf8fe5d5f2056f125d240bb82114cae0ce31e2f0fceed910fac6f7de9de4da88e8149b4b749979d37dfc3112e3ccab549be830aac9ae053d8474e1f248ff0b5e598731dd63cd62ce630b55933859137514e84ff5a4059c0410f564e477a1694ed2eaf3169ee8a9ba5069922129df8a94e4ffa278f4fbaf52a605aa76516938eca5be11142bb83087e6def74264e7e991c763e5191492035f7705bfdb17c22d4933fd2509dbd25840614baccee3bd3bd59a377484b55a09dc517fa298dc7f04a24304dc91002c000ae61bd5b75242c0680988d9e7e5c05f44aff949ea3addbc4fbc26a0ce3ca9f3229a4ebcdb6c754fe95748c2ec479b76e311273c23a1d3d4816de71a9bc26a74153c624cc449f068ebe2cb6cee7bb5e02ea4720a86a00a5e0883f4cc0a6d967596672646d439aef75fc13e0c4e0890ff68fd3a50efe3943548b446c2d2f89a2b16710f22cbaff9b1cb501675902362b0cb5f1ab9d09909952219eb933ca1e1dbf271a0fbe1fe40c928fb5d1fadb935b1fa84cd939310aa1d3c30deb64aa7cf9ffe7301bfe602ad3596e07e87f65e53b23fa5017880e70053f65aa7345b94829ee3db131813bcf76d0acbf69f988e88ca3f49cc4311ad327edd90e2a4b86910880f45c16c9ba8513fc72afdc4f4c272f052575b71e3de70f07161eda29c83bf83aef0fd46f11095cd4fcca33efd8cae8f8c2d0787112723cab9cac9ff9fa02bb45ecbc9879414151751bbbce8cad5c60405150e0819d076b699d9d9fb62505a6c104587302fba8fb17725e80e9732563411e576bba1a503b10ac97a41caddced4fa591ef6980aaebe3505df212201fd0d892d15bc08d6501df3a3263ff810dec62adce7262c07360d1de212b1684b239050a3c87acbc7025294124f86a8f35313a97ea373a701ff4187a7eb44e30c282c4b1c30702b442a606aaf3d5263716ff0fa7be107d0874581703f9ac04b6f8169872e94100ca1b11e44cea2bc63f51cc1822c65d6bafa8c639c8f32b4a60c928fd049282dad586e46cd622fc34f1fa5ff7a67d06a427fa22d05e485394344a1b41e8aca7c624306eb3a6c9ec319bc65d8f878b1badf3a4743ae1b39ae8f1ddba00bfebddd149f5b20836aeabee2c6710aa0b128fffca57783bef39e66db6df7b4a7d7fae067d3d65c63b020105437f448d644f4b0bbaeb0490ec5a337013b4ea5a16f82567ff2588070afdc6d0998ac6a11459ca7a8799dde3ec3411beccad252e897a360e1d4ce9e9e0a82c57c79a24abb99ed5190f27e43144f9fcf076becba38afc9640f9d18bb67f6d4b5652bd5393c8483ee348a2ab3431cc92dce30d0f069312a671fb283aba4e527c72781f59fb7f6d1704a3ff80d49fb53ece26f16a15ce40a5414475732384f8eefb51cd22b34b8e901c43eea8604354522c28031852da10e0acfe6901a3321a275f86f025459ddfe1d90c561bdb132ed4c22209e71728300a7f5ab0c84b7ced352ae3321462bd75f6976849448018db9c2241d2cfe684cb6c3678de2f1dc91a4b4b6c2572831d4b2036aa457476f8f19be70e405e2cce6e4e9b9e82be48e078216747dc6d63359debfd2fee14a0e8bc0de95a381272d3accd94617875e9c08162817d5294549584ebbe8dcb36d94a6cdce34e4f30c52541d425422ea0e2d1c00f9b381d021ecad3892a1541dd81a42a1eb8a7362b5a125651db02f1992efd6f9515f3f1ec66566f91c1876d159c61195383a4c5e4c89555fa026b5b3bcbcd34d8b6b0eb026cfdcb8cebe45884e499f7bd1f40f1e4a2144533f2d57e1eff0584805d5beb7d6ed7fe29e088379d1a7ee70805f0f8133d26156724d4ab6560d15f49053a1c8a8007a8eeab8f6c09265c4a545ddba9eabef6434b191d87570ad3c88485decce9cbf52a11895aeb82dadd9921522f368843fa7e246411cadf0fff4b236641cb516057f102e9875e9363bfbda62c5d40fccc935eadaad4da3723b7ba6cdae6cf88b3d14364b6d30b435627d7781aa1003bfc4c9fd145f6c6e82e58df863488d27e7b219949d554c09124c582591305a80964416a18f70b563a761ab713d4832a1780300c7ff01cc52be01a60ae53affd3cd4a0c19eaf60a077f792378be2d3c958108bc068760e1b920119b311b406a5c59658a9801c612140d9c8b15461701ae2ea1bf16ed9650d0a26b52dc59d927efcf8174a421409877064d17ae3bf17831e4759e3de408c616c9565eeb8cbf83729669fa7afb13e662961db2622136bfbc69f1a80a150a604c38bfde2c8de8eb5addb54825376d4f8b0935b6a1f34d2a82a29c8a725dab50649b796379d61e5382146d399df86de0fa51875baa1dd2b3b1490e34578dc9da393fdf26ebc36ea3c40b760e526e30280e05529ae6e5f9f70a41a6e36da9f9642ea74639a5631a6bb30f17f3403144d9b503d921917628a327a5422f79903a205f7dd33a34e93da5a553949e25c29f952e3b5f8fce39cd625c9d34c79d414f104a69532b4596bf7046c3c6115b4de3dded2bc270eb4963db75db38d73f2fc3719dee8730c12afa6cce1d867d7e949d7fb607e39bd2b09c1e80fce2fd76c41669ca73b9bae914f42a5a5903327059c7bda73ac88cdcde315d5de897fdc188b42ca521ad5d80e1a6a95c729f58e921fe2c258fecbe03858412cf0d4660c6fcb6c5b16be8342c970bb19390b7c393211ccaf35a680e1da855bff9c004b067780522c8f26770559af10a0fefbf887a4035c7456a368e3d9e50ba1423039767bdd6482e61a2e47829192b9131635608a8ba74a4f94959fa462aec7e6000000000000000000000000000000000000000000000005080f161c20", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 33, - "comment": "signature that takes 13 iteration(s)", - "msg": "1500000000000000000000000000000000000000000000000000000000000000", - "sig": "73bc2954da39fd7abb7ef32f531cb8144198e50cb52dc4ebc9dd5ec0edb90ba730716d93157995e37263b1456cf55882131ce6d537f10096dd8500d16166de80f5bda2f94463e8fa18e0b970871e4cdde1ce7d3e154d30643fd4a3740908fd8b1249dd3fc7da0a5ef591de4f308b44daf5018e17278267b56f7df5029a130c736f56283d50f97ea4d817eccc6008be603b19a70f1526e1d3a2b1d97a52402eada5f3c7898eb16fa2438b0e4ba9cd745b1c94f0a5c4d0be6ba5ba9f0186feb4f741260fa0f441f1839d3264150cff7792f5269bb2a82cc360e30a15f61b2568467d9c8d404784996dedbce426c71001748c691cc848e776023cbce13438aa0743b6ed57eb614bfa8fe6b199a53207c45ad762ba80efdfdd31595d7bb0da2d533aa65ab0ec3ced551a0b6ec2cc8a216944e670d7342cfa367542e86edc2086dd14de5c0ef8b38d677379fa986548bfd69e84bd892af28b4028687ad8c94f55ed56b50d611ba6de863c201b16b0b9de779ea393be40a79b6405bcd3f1f8685018c8fa61280289a948831ef7963f3d30f3570855e58873b9f9f02fd344f8362ef65f723fa0c5b8d628264e74cd4fea73ac6105be0713e80d52c5bf55c21c1f502d73ad0afa6144b6bdc227570b85b47143580c736fe4f2b201ec4f4f78efc3d4afb2a4d81c8184fe36011f7fbf197335ce1596a0ab39f8cabc02bc77ffc005665dbfa356b43ce805fe0dd2c24a9e6c363cf707ead215ae245963c5684ba85b55118d6e8e55c040012158645aa0d0004c184f826b7a43a2ce81a3bfc6c4ea5651e8dfd10fbb22b371d03e7dfbb3aa23a9e604d8c452a3e065afc05361062db3acd697e52614baf0afa010b7cce9e2c36d8e41020951154695bb13bcdbfac5eed9bcc8f0701ec5bd6393d83f828d3c85a591bfec897203109c57b87335c48ebe20b8c963ecd0d973c2cce02676fbcc38febf292616b05226c523a4bb6de9222de497caddef9e5bc65fc084e152f299538479f994dc79e19c806f0681ce43fded54c634427ca1f14b691aaa1e7294741ab9f86c15a68cfea5f5afa27e068564353ec51a39dc220ec0636a455604671d2d11e4de86b5d8b766b872563ea6d7a507a5c82a1babc6dee32af466d560cb9c9835febb4aa2d07d7205cec32209df17475eb635861e595b1f4cefbd9540aab01e1db317fd0ab6cf56a03f12688257028dcc7f344a87ab0f16c2ceb3a7c3cfab665c92a4b03a423eb158ad7d3a8958beaa417b4fc71948ece95058b56b9fadc25e9f3acda7020cfe201c1a584fcb2ef38c9b524941472d4651d828b17e7dfd31f022f2430bcadf48414aaeb49c21e52f40d5feb0e9216be4031c35f4b8cc6ade2ef156113fe63827179b0e6f30465111c7749b2e99adbd5e451f121f6832a4121abd9510a752a7a4a9893942d04abf4164346f4fd32a01ab7baeace93f678333c4f27889facecbf4f41ab234fe2b24c0de9cd58ddc969d53b5c7aa6ffe35e58dcbaccdfe9ffafee5b3f1d5222e6187957a6c653751b631f439b691d5f2cf91808f65de831e4f076c37b48fd9f96a09144ecd06510e3093429b37abf729e09e1fdc8dffade760a584cb6ee668a72d4619f421d5ccd663d379e6f143088c143e29f22ae9d0fb993e8447cf44015c36326e0efe6f16c547c3a212d1dfaefe654dffe6b231c5c1d8b3288e4ab38880b324249087822a32eea1ba798d2e7d204ea86a990c7974a37df998bbd7bc99d799458b231b4e45cb37dae19b46a95f597257e75df509b2f3a7d7e524134dc71eaa13ae8d585fa7cd45a6ca91ea96085e0092035ed9ee335fa047f4671d744a7b559b52a738f0d20ce5ca76127ab9d549b869a3eb6b66c57c1d317f68f3f6768a7eefbbc9ac06b4c45a6de768aa3b1cfa9aa19b792c23054ab84917628f94ab3dabef0d6445ebe8a374c4157408f1f84c33163a75b8f4646637dba50dc09846f1faf64589cfd1e5124f6e70770732df2bfd1102197d9a7f45215253cd9d05b7eef329c36a6fee9f3f38050658112b48c22c5561842ca24803b96d58fe1f627c2943ab1d9366d2abcceec4c6e55fb044e5a401d032f04f7ef2e49fb89f67da3a619ffe5702227a7ab06970f5079549dbf6bd4416722788805d4682374c982577b1977680e1d0a6af0e06ffe4103587b41f650a85db8eac9a009dac1f9f7589271f6fadf60c98f669f70989a913123f2ded18b2966abd257590ebae4225cc436cdea6430a3167f9f3f42f5cb135e11cf31b8e2e386ab51b6fddcb0e30aa3f2d8cb12373aeb8a364e3123fff93efe83fa89a44e97ccf4f9b5a107c1968436d8a08647acc88878cb7438b7f5545f59b2cb79e20ab8d4750243c6898859ee1d9d350b686aed01b2a6fceeb62cf9f824b6e76d57cb6f16566c4cac2aa17cdc8b72a2223c2f92bec38b0f481631d0096b2ae449370318bdd66e196537a24f0ea33aab87ac5c94bd0645824778cc329e76d5b38482d126a335573cbc81c895d225c3b724fe901ba5ee9052655ad9c059412d4cc25e00444e860f683558fc0cadcb33800e67c87b93dfe9adeca9aac911391632ffcee4a3ec48dcf03842498f674a6a8f689f058d825e931673d520700e284d3a26f2e5a3c3f2fcfee3d49f09775514b837dc35db8ea09e1db53d548ab580c4049e16327b5b0638a9f6e3513fc393122c9d9156ec532d462788a649f79bebfa626e38e261fb839f560f5276b36e462957674fee0094354dbb6275d09d08489dbe1fba5936d1801acd87dd89ad608d33f28a65d066f642117915b9acb32fc7459e15180e8ccc579ab2234cb64c6f4563f5a696eac76f158575276f773e0138545b904feef9cb44e1a13d3004245a33b476ad3e8170929e5e6adc68a12367d090091f7bca5493f7a448e88eb4f13cffd7f648ce368b092416f3b577e16512bb54dcd06e0bef24ed69396039741d37ff96aa0f3b7dad92fe7c67d32ec3c5d936c410329445c4126e027b1691f9964e39910ab4d1a6ec84fecd2934ea9e0f74f371ea279d50f70afb352064804d30fea26e4ecbea3eb6f96b7b4324913c71a2db4bd4a8f8459408eee1889f8ff15cbe14343403ffbba1d95c8b050f050e3bce3f394ed35bad88ce9e1235b3dfccfa478f730ca162355f1df0bb4d1205c8920b5b090851e9798487e3a858e8ae1bfcdd543209b1f8713fd1a80f6f3c8622c10315c1bf21c42d456667e64b1668f96455cd1281e3d76d3a52149621ec4beb651e245b8bf1f3f3fa770368fc83eae60eceb4f4d5e2b70e09a3015cb3dd2be4b307fb5b02db05a9225b6c21047b422c65ee788ccba14c86564f7fd6889a09a258e03ce3d802d19b33def3d223bd427a7cb4d9fd6814413e290a16bdda7acb39c477cbccbbad8c664aba0c97622e65e04c17cdcf51272eb8cf906ee15cd7ecded36bc66139800a4a7864401fe328f8df0505b1e13bf3bbad8b4a344a292d55a17019393e4f0105be7722837624b84a183ddb9278e9121b2ffcacc08456646653df5d5b88e77f8c61e341a869548ae1b286ad8b85ccb763e3d10da9c05e895fd49ef02ebbb60621dde417678ce965153284053d0fe38da260effb844a62956d02b1ec6e5c8ea661ac8775a95afa1861cec82c396a7ce98e5cef55429e3a4d239092f090ba10daa78811e59e9c094d4bd805ab89b5fefbc6cde6fdcee6f21b19c979e237a273e24d9db1d2a7aa6cb0443b5d8fdede41f5203442e658c6f9e63383407a4d67680b6f486254c597428f613e9478cd2b6e765029fb73ab72add5928752e558506e6ca46a3ae1abd4d2aa5f5d7b6556d07440b09166b0d93d5a939e190df2341415a132bbc0b742d3acae79d507628e1da15ae962ba93db1ab75e1bd6db1e99264e68db450bc6d242fa131b05fb73c050e6996c4c2f2ff95a372f12a9d22cd85eaa538db6e7096b765d730f7a35241935fcbe23508b18f5e61789af328cc00ba9f2eb9e004afb253317ac9b0ca2249f63040ce4ac99905508a6d349df6e96c6e675bd3acb3103c611aaead2046c4499fcdb17783bdddeb3c2c75553d338b877f6da0e9d12452943cf6040988fd036fd76deb09ebd8d24e464cad1b6f8d05ad9eab9f18c15b1d6a1e33437e874beded7ef0ca0e27f15229b6746cab74d77e334db74c013e45199e6b0c33e6da136c2004cdef5754c5b44d67085d9cd732bceb1cf20551fa0f183b1149caf1e39d88d6a5e0eebad539c3ec63ae9b2017d484866cbf6a9f5029e2cecc71954fe11c0fee7b1b36f8d18a0f138e54d45aff4f98aa922170a5d3f81d80121a29e6b2c8605214e6a807071675855099f305c9b0041caa826bbfbb216abf05339cc96cca1b143ec278ad3a1704653fa273d663f09addaa860cea934821e7f6d0d005ef1e8dcb62649907994c682481923300baafcb997150eddc0e3c1ecb6d911f51979e04cce3d1afcc40ad70eb0f3051189bafe36275bc313b5585126acdc44ba14a7cf6864a37a407069a266c252c121475d5132492be2120a43c80112360c847eb128b8b4b569153ef6205b6f24d0b5b641899b7244f0463324167071c91bb0f5f70777c8b92aac9cafa13181dbfc8cafa2485a9b612379bc72ebf2d3b59656980d200000000000000000000000000000000000000000b12161a1c23", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 34, - "comment": "signature that takes 14 iteration(s)", - "msg": "8e00000000000000000000000000000000000000000000000000000000000000", - "sig": "f35a6312f8a053655499f4476cecf4324dce61e0e98a6fddfeb391b714201119964d2891579c9ca0cb74b2850623808d9c2bf5cf38bfd051ec4acc1ae827b68383622793527e0eb3fa7be83c1f72b7abdd0073f7ba4244b7740aeb5fb66433847f3c8882811421a86a55833b05c1c2f24949ee29332f5ca5e9fe97daefc85ff6e9636b9d188c2d172c3f9644df60208fb298ac2a08490bb611828f1f5cc93c687b8a6f7441a8995a3cc50e894a11e9fc7f6dbd4d47cb087f7f3942a92ee10899d56a65d27eea66ccedd9a7722bdae4aec8fa6eb0b45be84dbd4c68560fde71d04fca514e10bcd733de9b3f99454b13cea8453e2c9cc5f29c709f2c131c972dfa2f47983d04d997ff217bab57d250da438b13ed640f3ea5017f78a394f2637bc708e0e7db2e5eefb18bb1c68d4ab59643135d08de302f9575548a2239bcc385849e1cec32765748940a011daa3f208da13ff97453e4d08fb668caa1a282530a0ff8e0d9cac67235be0dfc06d0fd5eb0ad56746191a84fd5ed68aebfb3f3d5fc2b3a391cb62958c471cf9533609bd564129aa6479f90c2df8ab3d5bbc51d9ae862eaef0e289c81fe4988ec757170289f5beeaf851888f1bb9b349d6cabebb5dd3d7fcc25c9e4dcca721f0e395918a69496c1e578662e3a42bab10070ce1c01f61cbbcd1ea2fe7dc18c318d649bb663fd7b6022cee490de54d309b0be08121765082bb5b634415cd7d16cd11e69f12d2bb927529554cc6cd2ea48612e93f59ab9fed4aa2a72fb78a7b73c39c7bb1c2bc3574fc7e2c209b64ae2c2e50781ff24ae6761e05e65f670f7d069072b6d73a479969b0ac345a5f1a214929e6b783d542753c9075bfb97dc72af2dd269a0e0a739430b04f0d6988206974d747df8d07abe115d2db2670fd66c2527f288077e49fcf1dc627464a963f031f438861bfbec5e21d973a5d7bb0ab20bc52ca3eea5c9f6fce2339e0a65170f5f7fe8c8d0fccbb1d5b8c5a5f7660d782406e18f75571e43cafd66cce56474b6d933edf42b2f01408d919df23334f5caf47a96b68e845f3b4e4e110e3614cd477ded26f1bf7c92f6ce93291ee809e61d48e824ac80317ce49224b7319d8e4e3c335fa9788f1aac31a3fbde6590c22216ee17d27e387805082dd3259ff68c162339c57404f291a7dbdf12f220575335e189d2c9536f412674e918d4e4d5f1761453d6a080b766db3fa486f961c111b1e661f28f3eacc0cb8e21f34fb143873113ad70331e2a915f0fafe29c0567877a8e947e13e7e7c677af3fb1637805c37877f994ea93cf6e2cac41817140b4721ff48e9a569bd285a821f5aa389f6e5b08dc2be22da23a31610f7f37dbcfef33a3c85b2975727711eb0b54004f5fa0035416018935add492f2cdc00cd367dfe6b4d16829755dd4ba7e5f25151bb9f02b31c05e26fade8b32e7c9569272887c8f32975fecd9c725ad92ee08a819e2f473c800d10c47798e921a69372b6770e664224f4672265d0b659680b0cc83f0724ff727f723d7022b966f67ad5242f312c5aa832deeb9a721957edc71d3cff4b19023462c9114c7341aab6d6f22bfa926128e98cd79c2380fa9844374e67b7317da9478add4579ded5fac480ddca2b9e19c4679447324286d7dee578e7c0b1358f2754c1840843189b45a8c69702f6be6afe95d4739f205638ea9d2059587724807d8f5033e9106791df3e1056b3b9d8972afc72746519f453c3b51a754cac0713d440c094f4b707cb07fbece5eead8a7c82fa6949b6289ee41e1da5b801924c24aa85b30c95c7a074f464c320c836df0da10898c912ba1b3b3bedcb64fa1bfe78477f33f5d5058e306c3ad6bde51908e9ca8dd5f4663185b1ac46cf6ae98059aae95fa0967d775f915256dfb90f80723c59c1d86ec4c700ba795ac0c8dbc87d9616602d7d67bd0b157fa9b1040c40c71e2c2b74d673ef26345c825baf86dc8ae8307651a14a06a341ed4a0d570b77c297c012740b2d678b6963ae1058e7b514da045867c42e04638b9cb361bc35770112492bc457ca1baf1811a8aceb3f622a770bd1958b5312201d9c2b228763e8eb0351a1f6a70bf2b8a746df2a4a354800faf6dd7299d4c70d0c55560f20a71b896553c731cdd65e1a8d83145f8c89fe587a299dabd29050fbfbc7dedad1aa67b96970403983d76406c04eb72dc8a77f4af4dcbd640e82e12628898345216aa350b8ca67136e4271bbd33670554dcec8d3e9e3f05424ef83cd7003454a9647f864ea143438519b0478230b794f7635a960ecd17565e85f2163061ad947bef93399f5f0977dca1bdb4999459f529fd7eb97e426978c10c20d8e6fe9f20aa908a2f734d88e0ad68f804e7698e69d065caac268e73025d269d06775047c028e1030d163730afd474b47f2782bc9d21af573080daeeaab9e39761beb659a0d1727f91ac9e28b1b332130962ade9a5c30376b23f3874e1dd9536d1c4db6dcff16224f1c6a98d4705e74a1a75ffaef200cedd73a79552783bb3757794c30c7ea0bdcb8b504212d7218253f777250369c8a65b321ff719d3918ad54eb1e5fb9dbb5b0a4925200f8edd784d1e5d5ddcfb20ebf6565e1125a8a3c3216ef32a2df02df47d38b90a45edcd940095d8a672bfbe505304cbe438f74437a34cf43ba2f6627c56f3f5b7a818c7dc754424eccf2446b0ddc03bac858ec34c1aa484738bc8bb6078adca3b2898cdd117846666410c490b5e6ead1e1fe3c231bb223a245a817d864a70743dcd3912d7011d70eeeb53ac1c0463359fc87a3cb179c7313cbda432b85374568db7610b97250f56a82cfe6258b4a68ac61e9dc281d5b887db4573b9f7a01503f243403e3e119f149ee95824f8370c64671b2e751b2c211c10c93ebd7fc8847e1d4441b0fd603ac7d8f6dc76e56351a26f8e9894f5370abc816d182d7a5f079827b095152e7886f087a9aaa5498dac8208b53133248f493fda96889a17ed9629a7c4b9e103ab59662a1347e0593779ece0fd00991cc9e83990e8c673573017329616cc03e90353a2eaf89af0b98731b5cbdff28b9e0af4478b631d6fb3748677391c3dcd342a80958b5e3cdd8460f4a3ef7786ae706991569bed078bd2c7a8902b1692a844f704f83477c456499bf6f743a12ef9cb1b560d060c0f864c8d84d3fa0162e1f128e19e16eaf230351d3a40999017cbdfd182037977a3ea8847877a1652abde40eee28bd9890d3e29bf626a1c7c5a7b02405e84be97fc9f3702d65854425c57dd85e7a680bfb16703d0d5c13a76696f15e802f2f0c757caedaf0844618520179d24d3f06273b87c9aa3cdfcf8ad05877387468d937904e2068522309518dca63a51c4063872b0b2089271b96dc1c62aca9423a9323295f2cdbf1d68e7600406abe86d54cdd1918ff3d763245da9a6ba4ac791e613ed73ee50aaa6744a2427aab021e2ef24f953042f6429fc451e39e796f6c7d64b3c40739b007699fed1c057f75d2d4659396d20f09509413eadffe78c75cef3e9eb65a12e332edb9e3b2e8e64795fac153a9f5bc30a7e3d35d65bee29cdda5afd93dcf7f5f42e4a448add1568d199ffb5774c3383cf8719bab694c22e5e3986dac4a679f741da198a228bbf4766fc7622ce5f517bdb900068c0b9b32cf4c563dea50bbe7025fb0e436ea86b0a8c2f58578d48f15eded8d19444906dedc2b766c376e6d0dfc90d761799d02afcaedbe35c9a30b3d302e4463186d9cb1867de8122009d52ff8fa8549451b438a379052ac63770cb04c8a80ab894efe019f414b48bc9460b33fa51978fdefa2f2701a440dfce6a50d92ac7df6b915314f76d7d79636877dda24ce3356ce78de29fe40f2ae4104712be865b17e9156998ae7bbe937556cb05cb155a600d303ef8df20940563b583bad366a0ec1ec023aa685eace86a495e5bd63d83b7d68039d18a83ce1ba5eb78f75242822d06601fc082518f59990e12b486a1d64112a80b80c6b0f4f3d5efb82bacf1b48857d06c305bf6f6eae815a39ca4753280412e340095d53379a0288cc977ba069962241bbcaf288468b9abd23118d3eeadbf706468e41199e57e9839b7c0bc1763d1b6a7a42187723373ddf6c9aa70765b0363dd4d5e70c9a9cb682b672f95dba7e156ac11cb3c526411b856152d124184227c53e45141ed12891d3b071a453b5cacb6bc07daa9404efcdacd33d7381b95ded01a2e54a7bbaab38096c08cdd795378ffbc055093e0602d8cc872f1a0e20e1577b0459953bdbe606a0147462c3e790e093c0110833f10e71226c1717cda055ddd82431ccdd7309648b5799384e4d776ce800ce7822cba4c2ef34045149e619cddd634f45fbfdca78df367d5f8c50392767b972ba01fa69b4907f1a610222943075ee385382652cbd5cae573f7edd8bb7f5f79e80eeb85669791f444ad3d5a9754f1e6520d27f563341ec0646f8395ee03e89b091a7e8bc5265b9f06040cccdca852e1b25cbc31c2a5b65b86d5ee855f00c7561c99cc8a622e8a4e7e2d238db3f48201dfbc381ce1ab55e7d6d0a1c5c5c7de5b095161b90a2696907662e3819aeb5a1198e21b2b760c994549747c9fbbe3152c3e3f56a0b82c2e4464798191d0e5206c9295b0014e606677aacdce3d717fb800000000000000000000000000000000060d161b2327", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 35, - "comment": "signature that takes 15 iteration(s)", - "msg": "dd00000000000000000000000000000000000000000000000000000000000000", - "sig": "191fc745712fc8a225adb8de855d779eef8cae43fe75418ea2b02611b979d39499c190bd59c31000eea61c0071a6c765f17f03310002524c8d1ba8df6c259405104df0a435658b488a3aa81c82d9ed06ab0886d456d7c021129f278edaf04477e9b27b2eb35d211691b43e36e65c823070a99e89e0000af939be62f1d95e94a168d953ae5d0933a39d223ab02631932d0006240fa5d3ef265519a5cec6bc796f932345f61e0e63dadf53461a1e444aeb7ff96b32cfa9c8ea4896ca5b5c58afa77e43ab34b011e6a93f9bbcb8dd8805ae7351cae0a0ca95756742077be679da919436faf4e386329000916e206545b18011221f25b8bbe71103aab949769d2add6bfb4082cce81a95b66dce001ede20fa6aac7b4c853df8205a432bf5bb0ffd3dae68e4eb195dc408450748143c8f5e6459a80a1f26b1b5b148d5394158425f8442a0d9faaf05a5ed8df9afa8bb97f499a8454615b626098fb3daa4c4ddcaad2709afebb8d6e1eb5bbe923ce5a4c41b3dc1568f4e8634455de6040cd3653ce5f3d63cd54834ffdf87e72e2c51cd2416041abbb51398e1eda1e22ca4e7b4bcd72eedde8581cbfe2b2b821918a338bf02a5771286ec7c992ad7e8c1f46dffbeb101e939f4b918d9a7b86fcf9940c12f0d2577e57f2702a263f177ab0467bfeb3384647c179f88ce508eb0173bfb6af85fb662b0861ee8051fa4c1820266f8aa6bd6f5c6dfdfe31f15a86df16669815df1af36c2c03d10a8364f488dfe3c266d012a69e538292d2799254da27d9ab3dd900185d00ba45110071ce6132fd2fbd6c129977bd68a44bbe3d0d90b70c5c4d7bf3ffa9f50400168b4a2f28c572b020c175562dcc3160df4a71e77854d555cb8d40f7e773e532934dc896078b269b719de189daaa17187e506d7c2cf06d7b7f4d7ebaa1e1b8f01be3e5fb514c4d3c23736b059f7f6b2a071a20debbc7aba923e040673f7d63a6ac223e86a85e665a941b1067f5a5b75d5a2d4622f30f61f813c9790d0bb62cba7c982d34dc6041f57f204df50b9774dc7300834f53f19d303479bd5df42b378dc28bdcbb81f8d2948b2eed172e57bdbc44d688dadbc2e30609e25c4ea4783ce53d4e8ab6ce921d43ec8e9ee82acfde0cb40789a50a9c696e9711e407e0a2383b252fd25f5d2b5456b4e4674a579f1c1c323d3abc7f1c14356c7dabf22d85ed4a9b5e75d40a5c7fb2912f4ec1e8ee6da96f352fe41c41741f312ffcfb079de51437467a4133c274dd539399b40e42d0805143fa8c7fa9743fca370059167f6f3346fc302f5b6dcb060e80b53eacc6bff176c739a6536f6b1bb4168852c68b57b787c330126ad0fb0414433ce263e2e46b27680ad072ac36d653cb95b0f0f6386c9f9db8285c3e06c38de485cc74b4610fb99714029cde977d9951c91803e9a6d864cf42215a4917aa69ead9509ce0086531d32cdc8cea5e0008bcfa709d18d0de3df22f50e87f59b7a512f3579c46de310dfc8cf95a7f940bdf86b8ce744433fdf50b5a9ca6ac87a7a7d1c7a2533c1c09790506f2cf6f8ff395d2122db9021a746411abedf1b991a0bd6071ced9135cf4319a45c564721945fdad887099efdcd1fcae03f4df332e0c7fbcf04fc66a286589ceb75c6a8f4dd2c16f67caedbe476ed4c57797078454fa66bd532494b83c03e2e5eba44b7d1f51d3d4b93b0cfddb290f05a24038871c766a4ac48cd041dc66a731b4ffb851a7648927f368e92ad45a369a4c9093f27476fc6e878ca8a9b0a915d88a3f55c7e712927ff961fde415e0b99bea5241e80c8eebbec3892ee13a4ad4d77deede0244f45f7c2f50949fb6224209de50d33047fdd60cc3610aa562adfd77e11057fc592e83bc2fc698ed156c57bfce86e444203b158948a0fd266f3167e46a061d05f5640fcc6cb7210cc51e8568e589fc950aa20daf7ddb4d46f5779b20d0d46890761132e23757535b37a009f078a09ed3ff17214574518eb1d03feb0a531f2fb59a44c96c27b834ded68470296be1ba9d4b1468d8e3c5daab19c97d388342e3c91ec82f7f9b50373add853b242b9274c8e7d59b4e84826144cdce31cc8a2d42052bc2723d1cfd01425d7cbf0a72bdc64e07e9f50410c0d84e128b4cd71f4c8a318da81567f320151a82d7b78d4369fdb6cb33a9dfc74394fea9b6e1b32bb4f2ba5fbf6bddf8ce0c93cf18debefde8057e0fe2135240021c647b48bb197f3f205621bf34e0bb7477d903d01e0814774e1e3868f30bb090f67dbdb786baebf443ae31e517c3e42f18a1651efeea26131e763cc3190cc444f8d9675445dd52746bad7b80854f9c4a5836167ecc0a4c1aa65a915de8eb20ff6dee1b3005cc2cb5cb94fb12f64bc010cc382b068ac9dc3cb78e8eaad7bfbae4c8527c44083dcccfa2916fc54814b3d6f37033dcd7c8d56efbfc358af36d8c39eb725d09e74be2cd280ad85431017a50a8445306f6a473da9edd363b7111946dcd03e8cc79c030c6819aea4927f1975fb991882ae05421202024f1c9373ddd32d66f30c3933e5c209af4cddc4b485ce2474a7d49e3375867ef0c6ac721a643d578a44f33b0474c7ec0d734d7021fa5a0fded8b3c2cb03d451b4084e5ce0ef62330880e97234dcfcf4bb98902602aac8500bc367675018b840a0f4859c89e37ba7eba8583ddb60e08f2bf0e2cc60fe110d51c07036133c40cd98b8c9e877ed386b87d114449986497aaa3043cd8caa74277b0abaa6efe6b837cb873243c912a708d3e5de41295574d361a6fb39fd90664537ef8a13cc7ea3ff2f42c04c5b9593d6e34f5759f3b8a4d855aaa6372f7554a8ca58526e80ee5d405c265547c6a6de5e534e058aed9bc41f3a34477e093888b1630e6e3d71a79879c7563705d9ab7cbbe296c56efb9071aad4972f3519e096cee67107f47d32cfb3f484d5fcba19206d108ae66c6c62702ab3e0a3bbe70755b97d1ecae411710e84ad22912daf8a86dc1f3835c556b8d6fe83888846ba8b230a5f41ebb2684363220f2b84eb969878e764674b0b8ad64856af7c65513493397562a65d635cfa8290a037112650810d1e94591e69a7bbdd1f31528d866a9033e8e02a08ed36abddaf1cc74076e7e449fb08a90e247a9dfe7070dba8a929098a3ce1843f633466a2634b892d241af0f51ecc0f5effad44f7c7706b25a7e85636a1c67ea858414bb2e71cbb519e53703132206cb79f6ff3db39a90300fca172a283e5ac43f67d8a8bb9efaee9c541fa4086cdcf727ba0820485857118a963f6c2606cac4d292f1e4364d3389b03fb817974a323240bf986d723cb7fcdcd84bc7d4bfb37d3d94cb0818b569e92cb582e8d4a6deea11cbfcb3a93af11b9c59b71b3afe3f96d4e1550d2bcb082c89e8edef437a51c719d2b81d6ee77b5922c9da992afbed3de1ff76b7fca4e5f9e6afb6f175053e4fecfdb4696181cac8d040134b9d2248b9035cb9e2819711983d7797abf2d826a893c9ec78128a551a4f02cf1b9f5a6e1699a2f6abaa499f80709f42c0ec89deb8c828b35142f49fd0ac247e09fc5dc826b20ec840ebc858b8a265561cf9f616862f02f7cce26f22dc285646c1a09f7777179104d1c12c5f6624c3a7639c18c9ca58963f6db0c36697a542451e7a9334fdef9e2853c175d0ca93ee009d408a9dc9e0830b620f1adf11c3b1351b762d8dce5d9bc71c108cd154a879f277e8fb5fac3a6e7e538edf2545e09c2aa3737fab0223ee9ec65ca5d8c11b9e1a21c540d22fb2159f1a0158c6697616df55bddc37a516438b718261e700485e7a3a62e3b0d4e97b41f2b7e834acda632b8e9fda46397dbd75ff3761c9fdc2899499bdd9dd0f1df91b113e90c1765e27432b4e70270e380f6fbe4f8759e8aab00c7ec6137ef8378bd8f512e7217784f87b6692f1837e75825c0718bb8db0c60f82ad883aa51c70e68f4d37a2e5e8655ab792b46e1243cbd112a29573af7733eee36788f6e4d7b966a68a3874d0f6559b441d3bb11a8e1b4e1859ca11005c447e1d7aaa9f6fd6e0f177c1bd0d15d05312524edd18fc2e233698d35a0f8fe70d4fd43e3855cb10f0d9101e37f3d1317c9d7d78a57a15b736f759d8eddcf1ca94e00282db8631f8bf2d2a49535ba858429748df9b8dc592b9545fababe496bed4bb525752cd5e338c6e666f8a3961df74c29b8221d720a1bda05fdf01f92d32b3ed9ce8c3fa70f21ef30132cdc30bd2ec9c5aeb73bf712293c545744734f180b327a08a6b4749273f6d853429dceda4471533952ed47b28f78ccc91ffea3eb0dc56192355f64d36dd001e822cfbac8ce9e2bc98d9a56567d77064e60713a0e7d676b17be0d05cd181d0a9e101560d4d60153ac59acdc5cb8bb3550c27a39b33c399aa54b488272903f97a4e3a9842b30de82a18eadb3cd897d4bc92a23c576d780a83829378e15248c027d1eb76bac3f1f7f0413cb7a5492a9c44a3ee78d42293483983a7d1e90fbbe277411992c034b649c8d63054a02b17d97398a87fbeed698f0e890c479b2468ced6ab23a986ad6c41ac712b137afa93df37fa8080564cbf67bba235914d7a8f832fbacb7f3d5ffe2097f032e32585a76a9aae325a5cb121619344a6466696ecbd11d656d9397b4e2142f35580a22292f3a3d46494db1bbcbcc000000000000000000080b161d212e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 36, - "comment": "signature that takes 16 iteration(s)", - "msg": "6c00000000000000000000000000000000000000000000000000000000000000", - "sig": "3e41b01c01bf6603b6d0eef00cf02bf550767797e381cb6530affadd09100fc963e864c42e24059a35b54421dee314dd6ec4dff8c13e761061160673d1a94008b1131aaf1cff6cee99fdcc7c79991723d46cbbd3d9e891972c9d5f52f20bbb11c54e5ecbf557332c25c9b54179e6064eed210479dc6446707f5204aeaad9db2f8f21ed5f602965bd137982ab5132d9f24caeae6bbff8ce95a4ed47f63d7d258fe1760d8e8a7e4a12db37d3ad11131605d2be5eedc250feba39574bce461ba88a0ef59cc7ac109b76c83026afe2f2f3656f1ab477af4b49eefd56c9a00ce804427d78a5867ec497f07a5c488762c8883b839a584ef014d91e909724ecf77fefb2fa3c68b548deae9b3efccf3eebf62a5bd76f966f7489a71d85abed7c06bef1400db6f188aa57278a874cdd8613b64334c59416d1b64b121fd2df20bbaad74c8136219086fee3400f6ee37ad03fef16a9bb7579683ff421e046f9cd407b61e9a8aed130c60596de5be4ae7fa50667db07505af533bd199c12128c03a7d740c0ecca1aa7f33dcc60009cff2b6339bfa041fa82032eed9b2021037fcfb00c53c096f608fc19fcfe5fd0625c3bae39d1ed3067f3ac10344eba67441919cfff24c90bab23ba36e2c835ca1059d762108698cfcec610e711513060845c189c507e34a3208fff884c8825c4ab3befe08f36e378503612f926fcb99949d9a2cea0b2fe59542e69f1c8f99603d10c02df15ebc4193ef22cd45303d24ae70d93417e87959e209ae8ae6618d2007c281ea8fa5e73be5ac16aae20f4b037df559835b25a80502543709916bf1f20bcca93497472adf33b43cba42edfacb51d3294b476db006cdb534b0e0659a90a26a9ec68b3b335d461a613e2f03e94aef417983af6707a543ac99cccc341b540886892e209f333d4426f6dc83210d602d357ba70942506bf391c747a86202ffea712e7f0448105cb61310dd1fbf6332ba0d6e27e3ef22cfcaa5834df1b7f5e8eff50b4aa7a3889a0dde43d1b09246aeca8bab043044f7daf2f14a61b7fb71ac24c804c07619f31b94fba83a586a9be34706386683e5e3965ff4c242e524bd4745eecf30db2865db5f217c4f9dfe78584895d4214abb2b7084d7bf64363dda987987e0da8cfed427c20e83bda6550978d35e995368e6638c055a971e7b8460f77bf59021f3d3cc4edf36a44ff18b618d0b854c5c3cd1c8bf1006999c99def36fa878ce03bcb01bc48e1b5cbd975c7afb9d3029317e4df17031d97315027dfce18dfd16ab5012eb0a24876145c0e2262627582884b18619b384ace8fcaf35dbed5a95c38096aa006a94ff6b88fb7d800574feae49a7c9a8b29c36ead729fb194770e5202c5eec7071541090c0315493547da789b15f2fb28ade9354e0b0952c75541245dd0d82e0cd553911f2f844daa2af5e34dfd2f886559b69f038e41dff53cdefba8663cd4c3b270e41ad01cd9c69d84117729d51bf9c0b8249a48a00ee7662fe0f45e3f522b0e97547c6d382c205c47a2711d20cb8a6d18ed6a227c49a2fe261e9cd5427acb8f8b09477791cbb13c161892891aec718a2089181dda7c8f8bf7774ce109d8aa4bbdc6f6451ed2eed41561d7508fdc123fc7018b67585f5f7cee14645dadb2fb1b5d6de80cd5c5900372400164532f1186b02cccf8066dad549b3949714975cb92edf3f98df302ac01e5f7ee254ef0d76f3a5afabf805e81d95afcfd39044ae1fcbedadb35e737a7277dd31f9cb5c68f0306495b5981efaf676da2d28dfba12fd87625e14a6757e3ab313586c68dc8ba7ef1e90c521fd13e980fb973210ac36ff5c223cc258241ed45138b7b8044fb63e8899faa15dad544f77955c9dd39ee11545a10e613f09e01efecd048b9b61c9f89e10acf59c4fe10e17f276c0d72aeac60971673ae1b13ad5d6ec116dd92df3e0d6cd79c71893b812d1ebcb6d2e32d3044dd0815c4aef995486eb6a2262d5ade9f975ba176bb3be9ee4a0bb2b9b0dfcd679f3772db9c7e5219ea538f1bf4036edcc9e52623c9b209e092524d023dd200308217b7ad3df4aa312ee8d503fbdf5bdcc6578f32f4bd292f5e7f0751d6e18f5500ae5013291941f20355003731d764e973c17a7120daa0a790e5362dc13ba377aefdb1e2228ae1e2bce9bbb66661f016fd184973f1b156bb2739bf4aa6cae8b935273f8e821de354a85a21ac92b08b5b384e4889ce5adadec098a2efd960e407f6c1c5cb51776b49cba25454633b0d804dffa9adaa22a62475feca711f510dba1b927452948875c23fe50eb04af36960ea8f322992d48cc136b2cf44c4fbc45e84bfe347a1136e11efdc4ec4125ffc4feb8a7c2a832e29de612ec28ebb59c3d82d45323fc35b1a0136fb18aed7e761fcae68944f6bbd63b5c66621205c525d0c409d7472c263e8e1b556aab713924c44000e347f743ab9768c46cbb654d699bb0892f3461d5a8dab4aed8d1f0816fecd297a09d2ea3d578b74356709c5c019e0c6eb44cb9185b96e78193fe5f3c19437057ea356d8f9af450f5bd9c230fac20efb37341809228116dc5676f43cbb970fa1389dc8bcedcaa0722e8dd0aaf54eade137e8f18d9d7341867fc2799d05681aeead12903857ae7046fb335cc290e5756a2812ec9925ecea01919df31f0b99ba516b74a1f29b17ebf02de6b712a12786b8b280cca0c8c6673ab037db91612d38b48a1a4d3644b0b52a4c3ce262edb5691296d2d53071a14b7227e1892927089a19dffad11f1f1bd0c25e6553541d7483ce277a96bdecac31724784aa9d933d3dcdd3f42ca1929663b5e1102430d9ae33b60421b37381ebfc65c4eb23afdc533170018ff2a3009367e32ab9cf83d806dc6fa796de92476705eb434075206e0e8e1007f94dfec75021906fb1ba90cb1ab90c4e726a03f8b1eb40e0b6cb781b84d44535945a2caa50c0228f1f63509208add3951d6fdce948d316a7ac5422db6e065928bb32d495730ce8c3e78bb7b909035f90c01e4b60bcad19224441d2495636a38904c45b98e38ea5ffe4a4a5dff4ac585a037e129a5809a864fe763e21c3bc35f026bd61cc5bbbbd490465f66dfd719faae6e21836942f9bc56fd728dd5c835943e4289bc83e5eab913385aef4c526f42b9143c3a430b399cd469395c13bdf91f0b61e1352763321e439a15f464df8901e3eed66788d91fca51a81fdb8dab7a0d9b67202b98412f39015bd390496e0b22209353d812b8d4a458c2e5de71ec5c17c9b034d892855fa70f1199a942c3ee4835cc920603d2afe28f51259892a7c610774e4f77fc40739f6bc954dd7f30720054dc4a9df4f302ef6fc3d379c67772cf4a5a6aa6024a2e7b60fb430fdf2a1f1f44ef966f6a731886b8ca6de72dbd72b648af68fe543a7534fa42851c1b498ddac2b6f94a18009fa03b976e5592a818e87322ac344ad4e981b590bb57980fc903bdf0d84a23ebe4eeaa5a658736c7b91a7ea31462a7bef3cec35630cf5dd82344b34463eabe9c37468a8cddc9db577365cfe061bac2aadd6a339c35caa61944bbd76d1c5f605399b9c60897b41ede89d4392c9881d8ef54c5b623438633607c917e5a148f91f69330d2cfc3a07a385fa636b1b176fd2099a8532e517603f461e1291b65e4de6c534d6dfa3a50f9b0cb4358dec901823fd3fcca7a1296118b261f470cbd2e8438a6debfef71787cfe3d9fea869beaaefee5159c7e0e3d98e8a2f4dfda6a42e01504c04660ccf06c249736aab24968c3718037a9b693c3bb09f3b7848fc70c60df838d0080595acffaffbe8184771615896a42664c3aa7a25c7365d696a23644c625bb964b699ac048f78320e064140ded9c3779cb5453326b7ffb66c14193420c46a16537011d8c058e5689b584feab9d82c3387d5cc9035f58b7f9d9cef7fa4bd8fe4118e5c8aebcb1bbcc831ff5cd2430ab3b90393987d7906d03f92374eb3bee8c65ac043b038545da445861860b59f34a28112750eb6449c8daaca5a3a8dceffe8c573ed9278938d6bc47e8a0c0c645040e1610b39744391a9191bcc34e08a31b9abe1ae69ad9f141016fcd1b7d4d5b23bb709b1240b3b7a9a1ddb622ecf276ed63f1a92a184a7cb80adf9dadee15ca87972e530026be137cde18cb59b0232a12ff5cda724b21342108ceb83fa30dc50af8b214e638f0e88fb2e11664f6b14ed6421022661dfeaf0903f732622fcf19375daeee2ec601d3e3749c339ea85ea1f02938f972a0ae2804cca49aff7ffde527d084e0aeaa45fa91660063bbae4fa03c3ebf20d00a8b32f17c4c1a4672f66b8146fab2597620aa8bd9ad43b7bb238c851b3c37e8551f6de1a8fa41dc3082dd0d202b75524cb9685812c9756ca8bb42ed74175a9d6e70d904713b08206b1cce2c822bad661634536f9f51e753602cbe61fa783e3b6f0b84de0ca9b89b8b9ff8432745b45d4f38c660529e8626ad737c76810b97b89602fb9b9a8b8964bd8c79f5439cd1d12aebc7d240041ad00cd244ebf266a3b2a964d6371b3bf6d676f5fd97c1a514c3ac26c0442e891efa56fd67971ecd81b90da6ca20fb2a6e83aae5581d4db5bdd28efa1015066788a90d1dc1d1e253f5a5c64c6df0b0c3b588006cf3352606290cbdaebeeafed0000000000000000000000000000000000000000081116182123", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 37, - "comment": "signature that takes 17 iteration(s)", - "msg": "2400000000000000000000000000000000000000000000000000000000000000", - "sig": "45f7b98506b52cf17ac1ca661951dc3cae6637b2b532dc3dd3e49db1ee098bcfa20be1b6ef9a4b278589b8e7c4cad32a16c5600901d47f0fc06272628bba29815f237fd0839e079f0fe6739dd45fa3e5a93d7d1311536c1daaa2d14179eaed2a2933d17825f88e034c9be9cf5f5934ee9201e3496a65e4aa7a2fb18cc323cac3a1997cd9e953654fb504f1c9dbfefd35e09aeb6613ab4c06e571a782acff038df56a04e03ddac640909858e543e9ca2015ada794340f3b8187faad2c088e9a18fe7087f8bfdb3a9c234daedacdfbffae1dc67e04e429555d53b42790fa1735e788d930889ef6618b1e58ed5c327ea6723f2c11f1f466a9c145a11447131dee81550ffaccd5663a5a14e25f21abd330f71fd7405dfcfa93d8227b142cffe58d575507da2c19a631b307570e2783dd4d77e73ab2639c6a4364b3a2b1b7c92d93366f81e7042f2fff359b78630f6c3203b1c88ea9bd0fb7c732f3e5753139c8f9103480e77c57a6c8705ea245b47cc0e64e55ed2246d45e93cd638d0104fb43806b329469e2dc4fec7c9527b5090a47bdf0004ca0a6d4c747df14e8eadb88af3951cc2fed195af08657f35ea1eafd6bf53755b4a66153d4f8aa62f1feccf69f92ce4d5338c422e6743c23c51326be0296d80fded7d5b01c54abf10d530ad0f136313b3d19e55c5ab9c584b80e83f5dc99960392359a6fa718b4d1d6be467de44a8e6678d05d0a1261517d4edfea6bf90af2a80a11fd9bdde875fd340aac5880b201e0a935f58489eacd10f9c18597e51ac0604be6a5df0fa83267bbd28827668fe05bdd26fd7cf09a2c8b3f42df35412a68cb3b45679c76e012bcb7475522234d0c50845395c5cc896a336f1e216e8c62a5d65cac474c8e48f0af8d9f160f08208f196c4cc4c9d2dc4e592ef1407ed6da5471b0622d789300259ffb8a4ce75130343ee0215a3f501291efb8ea7a43b0492264157535d79e8edf106f9100573e486915e54219c989c40cfc6bf6f058f4a34f952a9f10fdfedff8bd173be598f2bcedff2ef2216386cd1eb93b9ce9e34179a29569da669b641297b3874f7477b8d08075710c9bd83cc722fd94402929eff0961de5297e803067cdffded15c42f5febd63f61c8f19b24adc1f599454b8d40b5689ffe5aa759517be2d31c45f5024f8fcdacb7fb0147b4a67f2c2e62bed6d99f2ea15f36ca051b29082e64f5272c7628f923738ded2bdc0b58b2f92cc11046055351bd65b3efb9779d3bd0b28a0e2ef1f2e807b5eae196c2bae7b07149012a8d52ffa80644c04a0ea7cf5226b008e7fc40b95fb0951c2bc9416d60d677ce96f86a655b89f504cd047eac6c6d1905358de689b518cf8651227146fdfc8306e574a38ebb39d5db0697c8320cab784e5c0e71f33adbcc5e2d38894e6006207dd97e545f83201bf1033a107c92e6fbb63f7fa9d6d80ab96b2baa89c89182198e1f93102cb9b10a21db60fba15820c1d82244dae2dbea9124bdc44f69931ee97904e15200c91bb525b3dd37837224c5c52659786e53701dfb0ab836e5ab3924beebaead548b67119d63b52ea88def1f28a0492aa047c346e5b37240d52174f609d82a46be480145f6644647d814608d2aa2077e97227bf7265c1e8e41e263abaf76eb4b705b334d7135794e4e633be36c0eadd86c9978cb5dcd34d85f959fca840a837613f35da365530b4a075bbb0de3d5251138390db3e71da1377527fa3cd5b15fca0147f9646b0813a64f5090b5bba0c68e6fc3e328215877e7f1405346624f8ede7eefa90778982fff9ecf84330bff13e6ae837d891535be7e9d52f4c828357aaafb129f7f1472fd0ae17aa73ea80894496d805a8a393e1626b1bbbb8906f3bc1bff8beac84d1b678fc2fe0218c5983787e7f98db793731fe8b5af27c90691d9ce029db1c35fb9c27659bb09e01b22be955c64fa62cb3cea9d396c47a25e3ea80aed271ad3eba5e48a743538a86a9471d82003bc8708ebfc3f2b8433a3ef418da91281e24525266b72b3c975a030dd41d7a3f76b46eb916c951c27c6db83f56338e12f4b8d517f1f39e18a954ffb01a34adfbf8b14ac5166c7ece5d8ca2e236e35a339360366aeb62cf01242ab11d18a95665b7b3c29ed818e65e14cfd1443e8ad67e32343c90272ba9a262653725d1338694c77f12dd1234f735d0fc59b55de9733d6cffec59cc6c4b1027a7633eff36fd547b549f2d54577b4d3e883064e1f96eed8003c44eee8ade5a26d59d657355d17ebef8264fd07f006eedb3a0182bd6cfa708803d5a521a669fbe2ec256dc69e704c31174fae1f5ef3688a6f6a5568b872d7a61251640871327350d6e00818538f60c7627ae84ef6773a0024790a93ba11be699317711ca3710aa8c7f990c1533277d38d117e0a8ce92490758dba144de16a4fbc97c2ed2fd466361cfb07a63fea544a54a1f4b04780171672b8f9987214055d65309f1a41c78befe703501c41520c50afa576371c91d1ea726d4542172d97f38355b7d7cfdde25010468a63ab2cee6fbae270a82f99384d46322e84c883996ccaea15eec01f07f9728cac753cda40ac6954b52c751e375482776788155edce5a23507c4628ecbf715262209ecbd7ba91948ec891571c214798e96ede019b5c726c8447801bbf76d565e7201d95cfd47064caffa3ee0757bddb9ffac0b42f4a804f68591cc7f2e0fdab131a8ffe5a7c776848927bad752f01dcfff7241003e501623ebebf2ba036100f3dc5e28a23d18d276476ea014494c693d9f4484267f1ceecd7e1fd6c75e74b416c795b516cf9f99a26d669bbbc9cb2bff8de6371bd4ea97b35fb8bc684c464d185e3bf40fd26a8323d507c7b31d203aae661add13c6531f7b56635bd6509979de917268bc0b4489f5cfe2bc2d117d5f27c1cb0de2a85c024a555a815eed435b28fdb97debb7fb6631e72ca1fbf2de560a54496b7ea79f72e41edb21eb28e7c910f74c85122240175309be4c419c2a6886803313d30ef93f587b7fb0232c91ae6d12b54406b495362276afa922af02ac6357b04f817b56cefa7a326376b82aa10e35a113c61666e9b9c9206313318b7e1097166568239eb3455478008e42542608923174fcfca8151e0894decc12fcf32ec9a2c12b48dda7a6896db728ae779d856bf2efbc34d7423eb48c87e00f4b4727420cbf4555fe5a46c63505fba5abc590415dbdb842abd728638844934609980c95985e3f127178f0fc463f4180fa74b5a5cdba1039db813e68fc1de1334857b55dc6a6aab0c4c665a9046a4191eaad90bd9b2b112a46e2a4c253d28c175823334d49ba9e07e85634c24dfedb348e592e4c994a01a5fad53964b7af28f431a338af16f28bb22c645d65d6f40150e7f10897be7b8496601551cd5c813057f2e38a5d59f310b5bc1b52216c467d1916df0da345b3e2f0aee80f7079648876cd2cf3127ef3f18acc55f97e026e3760ef91531fdf81e71c0af14e24bd2fc1bd280f1cbf6e82495e31daa5dc2eb9c0d6568e9b980da14c4efd8e80e853bebb34c259762d2e5ffb918bc2f85100f8d60b0e2353f0fc1f7ed6b3ccda17ff778db565d2942898579851409b31c2ebb860397780174ddac7fbc5e558ae04d6d60c3098adec601882ea9902b33fc43a92e16db396e345a995e4487ab2d07354dc65c04dc873cf13e1f189cb19c84627b892ef586a38dd649c02f3f4efa44943387c493b5edf476f8e68444c804b2543d780b4cef1b71e80251b1cd64958ceb48cef6956ca74a590b6623c7181acdefb343ff65ec776ad12594890ba5b77d1d2d37d0a859aa3a0037dd70e1c0af0b686559bc2c619ab8ca3f649c38e6d0f2b5a6458743293ad38ad26541c843bb00c8005407bc74446206af67173f53043d9c95c2696cac7359023fcdd655dcb2d8afe068df092c8bcc3cf18e438c12848ef078383f6126a5f2f9b4620d193d6c8b8b9f1265c827c4a1928e3e523b2e653efa378800943cd3e1cc639ac3821f7fb44f5f01290a144f11d3e26244163e1cf60aa627d7318dc3f42fa9bbc0292d6fa61cf3e04dab98a3e2ed3a1cecbf5f2e08aaac5650343934958f15a2b915f0007c7a251623c93826f2e1a1c5c8aa0879af6dfebca672c616917ed96ba3c4757ef0714fd8b88e0f21af580e094d9381a5a8fe18fd34156627dea4cc154bbd9f2d9eacd1e40747222015fc93671d745488c8848c259c7a2582c0165a1afdbf46c9a75590cb825074fbd410410a94568c444b2b964d331efbaf82771524a6cc0bf84ac2ebd1f1dd0ed8033178e79f24efeb43a0018351b13759035120dae2972f6e314c671e3b918ed9ed89234dc27c17ec9abdd3b2fc64d8e562ebdb7c90902a0931d6480386dd633185e15459ca4471177281d636d6280433d260a51522b251579833e53ee757c9fa2f87ea1fd86af051381d6f20ad947f5981300bc93cf5c44defda770975bc1438b053537665535a9c764f7fb7f03038305f4eca46ecc6faa60247024d12eda7bcc626d924894e2c538dacdebf4fd2b64ee428f8fe30ff104d21b8e1f3897bb86c567a31f153d4e8ff3be2d9a539baad2335762a010b35bdfa1a1b5df981abc8e612314445dddfeff0fe49b0cddc000000000000000000000000000000000000000000000000000000000005090d16181a", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 38, - "comment": "signature that takes 18 iteration(s)", - "msg": "f900000000000000000000000000000000000000000000000000000000000000", - "sig": "6593932b139ae1104d35507504133096297012e45c9865f57a7bd6fe87a6e4a10394f43226ec77841ad10ece333a381c37c91bbd82a63bf87fc8091ed29a4599042715ade54f5c94a6a0e1222816e112b4abf893f0261fa5bb5d774c6c8d35bc1c447e17d3dbc25798803518cf6f6bdccc7e2e77d77cb8e6ef24564a36b5054d91836c7ff1958b6d850d25f762f78b0b55c2850131437ad677b28b8d11d91b16508fb91f250c1c59adc4a2415ca6d20acf50c90808b5a4e88c043caa68a9e6a2ded7dd4f92844c2440589540fdf7e48349ba43bc26c23da748ac9d75f0b188688541de951a9ca4fb918572c96f7d85a040655d459eb3130c03bdd865583a2bcb382819c0b59f80e6369dbbc0f5d5b40010c2490c87acb9b50ec1a998be39694ef591a3653e9364c52137881ce175da1a97326b33a969d035cea68a5ae85e5febfe82cb5ac731f88a0c895896680a9ae8b4e7b3eae3f7a7d4a10f4063374f317a1ba377a01a3433e1242b2f00c0584a094d157c5be1a864b84712889c016e38fe757d02c30d63dc4c5d087f8c78032865ebc87de03747d03bd6bc32eb9880e8b640ab46e630815d11b3e4d88edfa6a3c006b568cc9648d4df218ab91bf1168852d4102f4503061f96bd401491aa76ae8314ef47d7941a767fdfabff79349d089aa5198248cfb2524ca6489ad58fad9ca4fa6d7d1ddce1fa88c3dadb434cd3a1f49168460b36d9987eee09ef17a1a789a457b98098c85311deb3e7f4d7c2a84c1c78c2db3e9823a5b47b9e313458d8023357aec8cb45fd052da9404c731062508ba31db91cb670f474319948538dfb7b811368e4325b24ac77cfe1f852bbb33574f175738f6924aa937aecc41397f8e34d3c75f44d6e81714a98a552a766089b8b2059bfef2f890edc17f9d98df040b3ad9168c285be95ee126ffd3d75658571f75035a0e9fbbbe66ad6a85a80077d21cd19bf9490f3fabd69991d6ba2589e1b9a3b8e64f0b879f3d80119e6715b827dea6bf40c09c02490e60b37e13d09d963a841fa58a4feeed6982295eb6be66def030230079a61494fd7295143c3a99c9fa722e1081853153110206cc59ed26a77f9125eaa98944d26708609594ddfa78c7760a8e9bed82e85cd991b2bc5ef7e2216e0bca4d16017749a1579b54dedcb165152d9324ee63fb7012b2798da17d3700c6d8280c9d7bcbf6ea8467542e92c8a0868ee9d5fd08bd397641b20d7ba15dfd079bae86972020c1ea54a0e641665b9f20dfd7342efeaf45e2c0682fcbc75569db5d8fefe4e1cad4e8865e86ebfa52ebb4c3bb1f9bdeaf2f179980424a62eb40a07196a78069ea6b33f52dd50bc42245517346a846a63bf08bd27d341ebf829807595f12ee0b097b917529cc0c4dfa7715238eae6cf336fea3004416f18546262ba801c8bc255d325524b7259bb747c3f8ba51aad3fd54d98c882c3c4924c3d01c2846690608575ff94e6778200ea316dc7e802f889a255e642c94e43cae57c68ab4f5083d15921e4abdcee8d7c4e9b60e43cd3a234780c0a6173b6b132d2482c7750e5aea328397f6c87898cd2254437a37f3b0e65b3f448f541f8c455476aecb3e5d7494188ac19cbb5f2ec45e246e66202dab148f2d5c0d388ec1dfa17495c9b3d255da2f48211b1ae87b2beac31735fb79561a1986e80651ef0f32bc9181fc911ea32855b5c0cc3a4fd807c5fbae608d683e81b33544a42bf1f89861b4afa5585b25e57e651e5402fee091d6bcb0444ece3e2d907031716c4488b6391c90446da0991eef10d982578b6999beae142cd85aca38e1a6ff07553f3254de236620bdcd17e24e9fdbd1fd7d672799211cfcf4e24184cbdcd3cda0d8d03f3dd76b0e03606c63f8fcfeae5ecfccf4dee0d5158567e86e3a4ce343ddc3c4c3c1449f142774547f25a9538eb80191b239e510ab0d5dda4d1d2e8af018ce177c6877771a7eb5dba26429f7d9772af8baf8220d35b28545d0127b14b524aa5afedaafdd3998e6c3bbedb0b1ac72ad30073560ee23e85432659a3ad60fb95a731b98884cbe826d3205696424886341986e933b97d67ae5c0886979be4c32fdb94aea47b9a3efb2d062806ed25af606e5072bb4352f3903711fa94a97a86c2dc2d32e6ff8dd221fe07e539f22da92a158e8a8df936e38d02d53d1b0fd80b63b6ef40bf826618f962a1d64ff361e546b73d2c7d47a5c0697af49041dac576de3f6918246877cf50504b641a457fa8368caf5eac325e468b07ed722c8833c66a2fc42b1e3f5eb588190deeed2c10524f1b05c6efc9d72a6a1f4833eb58db9a5e11b4704d879d25c998236fb4ce4b2720716c9e66cb339cc2293bacb546260385e2d860d727d952b4bf07618a04b30bead38bc41d2fb7fbd49931e099806a6d255d2cdb7fe62204a0efa2a883c4424bbf875af04d1f7cb2d9cba74946b0022f614c6a162b643a212523e7e7c7165ef5d6400f1664cb37fa555398f988057fd8aa3918ef644fcbed19549db991d5ff2c99cb9f6be56f24aad7d7ee304ed38240a609df19a2b82571b33d9552b59ea540ba909ad64e3f8342e9c2855a3577eb910fb47b7feed8a23458434ee6e0b0cb484b11c63175685a0ce70e4ff7d03c47b7b9d1e18a73588e8546739e6e9c3aa0341f4c121e1c662acd77a614c4d87e84de703710455bbe937b30870d611ab1ec256a98fd884568b8e945b0d88400d87fba756c17311e3210235b3942ca5061fe91b072523720a4d32d174c88cbc65868b5d7d6113b948bed240d39d160dfc6daf8a43a1f6adfde7e71e0d593c82033e9f6b7a4baa0166d8f28c46114c57e364d70f0f122a7b463828cce26c1982f03cac961b42b805820b9af9c8bb2240eecf9daa990d61c42f01ed37ca723d092fecb767fc0ddf905ede494d7b2dabbc593360f569df195ceb1ce3741c08b60f5f5097830535c3049bbdcae2098b058ac9a50e4ce7fcd694d45b20e1e2fd86808d474480e131b17b1aa8ac351fe249708aecffa6a0c7bab3115ebbf8c43bc5382a2a8e2011bf859ad034d14d8d24d56475424c1b50bf85e534dc8b4745e79d6bf098fcdc86a5025284097b0ad564f6ada364837af4df60a30620dba25a3c5d739edcdd490fdf4b7ae7c67be90f6356d9b94963495d9c5c8ca7154b4b2ddbe1ef1c57d8e5e879a064c7c76be3ab86312657c3a971ee1f87735df1a2849018a7d1e4867c9ad9019729c3f43eace4f2916384acb25f5e340a534d6782aa7f348e37fb7e9895b9c4cbe732b4e7db46341f93cc8193407c0b699ebcd9b7e3f80b5612309b5d959a701d92f4fac5b251031db6f39d6339e75368fedeeb3dcb022b6addd77071af1f40504c875d19a5add799a7f0e5079fb39a7d5eb991b5bfc33f517c090b9bef48db0ae16d160f5a81143fdc0a793cc3927ad0ffe7df402169997c4386a6c01853a6c6d21f0607b209b0cddceba91af3757926195750de29ae82172840205bdc57051d7b273ce469fce06bad5f758febdaa498a3399d4e3d807bf62fd57819fee31a18fbf24e501b8990fc25253d6143cee42fcfc898dfe8a414ffca27356102762cbbbccc70158b318e5354801deb17bd202ac11627d6effddb25c172fe13a6a5756ad80b450839086a46dbdbe3570628747d733f4836f6d57c382a96c7aaa9d83c3a4d5b5ac4421599b6311219b733fd9601195dda1abe2fab8bffd26147dc555c8c8fa11e3ae36c3afe9e1cc98670d33804c0a60b2f68f98282c4b705dd9ad3b9270395470c90bc75a1483b946822a1b055852effd2aa8aa93a4d633dfb9022722982de780dad23dd5f2021f3c4c92e048b2e6aac3c6666abc2970a2684bb4d749b3b05539f90a9afab6b6cf5b05188ffdf36941974d5b622bbb85aa7ba3198104cc1111a914ae36291552f40825c0812abce4fc32a9d4e29d40a5320c29eb49905d907343646a638709ff078de5afa9b106359dda4d33da38170a5d2c17d57ed1dee1edaf1cbb019befcd4cfdab6e30ccc146fba1ed86968d7224630118137148c3d4add5e9797ac90bbfdbe1fb9b4f472616083fd8c1d72042af00c1960b4e9e44a820a50ae932975a0d4d64c0c26d61038ccc5132b40dad8ff9400758dac4f41cf7056069430104bb7de19a478b61340002562fe26cd831f6a7e662605d55dc6297b5c2cd248f1ddb5a272dd5851aefc0bc2e79c59a901e18fa9df2e3312a15852fa8deb733529884c7e0e6f4a247e51a2dee34f53323b98b2cf38966ec33c9b8d3697d056a9c505dfdd8cfd1e54733a85e184e46e66d57f726defbaf14bda8b35a1cf9b2a570e61a5ab1128d7b1ad791d0a6e0b79d51b5845a909513277ecb51774a76f02909851f57f4b7ab2ad8d3b3dddd74494a003f1afac6072d9abdc45238e458d639fc827270c37d15b605f2b91ab9f1a8065f5f65c0b4bec40a26f2fcab9dbb4c6c6176c4300e3425c0b4638b8dc0a98c341ffe5fc8e0e8e017f58647285633d0370b919449e1cb03e9e646371f17f85b7f837b9b641a38a3302036285e37997f144752059fe15cd62ca0d503062dcac9763514fd77751514e5a8593130f925012a63711a366dab06374a5e82e6ff0418434f646784c5dc063f558906426f99c9cdd1fafb00000000000000000000000000000000000004080f181c25", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 39, - "comment": "signature that takes 19 iteration(s)", - "msg": "a401000000000000000000000000000000000000000000000000000000000000", - "sig": "6dc1fa2984d614d5c52207db2528c102886bed81844437049d558dfffbb799f71a9dc992107666cc595a1981b75e49b36fa4a2b5d44a5d7e82a002c5b0fb8f8c811d82d19a84411ccdacdf86912db7dc9d0a8df1784a155c2ef1870d706583e16306106a0d0095aba7483e484c22c246077a743009b664f014d86d6358ef4f415e20d9a0b8ac2911756c72a1ab41c4d333f7376cd23405cfb5509e1885337b2e1f391b9e23517a0869f090db5e89a1f84075bf77b46115052a3cf25b3893a112a454a1b6c23836a84618030ea12f8bdbc2fd7cb2b789925b161f71c2e5300e08b9dfbfeb6e700cb09b9b101d64a4fe8ed2f1e66f7cafcd4985002f827098bab1722411845ba01bd994fe4b3b774096e353891a72414bd37af0df4f63580f5d3e72ff1c916c13bfa6828a44d281fed7ded0916e84f80c2bb41f818dcaef8eced887d7de680cd48d0e499913348d74f6a1e3fa81a10a079901a3db3e7fc6b55899714396204e4b442e156bf34915df34365f771b7c5617c7c521f88c43b03b738c069d96afb5a94b96071a43da76cafa8ba2d8f24f53fcdb7008ed7c73c5de081f9b7d2df75ba160009d05f1edd00aa44b6edac9e4f0f6413c743d925a70b87fbf551af7a3bc46b47814e02d7043e9b92bdaebf9dcd35c0e5a0c49bb53b6309456624e8484285d8e434d7fbc252191f69ca8c44f8eebce2d18159ed202a24b77e6ba9f907b14cd9308da274919f1c93b2ab6a6cd383b9b954d6fd1248aa35fca4eeae628d97d377d703a7bbe976956f5b46c2b884c6261cfb844bc3cb3f3219131e78aa2cfccb4276ab1cbcd42eb3b5a5cac311c340dd35198a42d13742290b0b23c5c8a7619acf12bb41e6ae570ebcc99deb82295882ff7cbef6fcbacd5cb0a0680d654be9b18325e8a11a33daf8ddb1118db078537be93a54c529673c366f89e2d497ec297346337fcf10b2288095f572dd62c1ccc4a830b2edbc6e9ed8905d688ff4333baacf412b8a95ff2de36b37a7d0d230eabebb0d128a1c1d9df3567f27a1beb31b822c4e8b535bb38539b9c93a8611a785d35f8afde56c09dfca722cf0364d99b9d0ca55dbc8f9d21cb69ae8b49791e4e1fa76bd6dc9c28dfaacf12add31cb150757070a39225510372b773459f8c86ccbcedd27015cf6daaa73f6698feb3bdc118b03211b261bd8574b116de124634626386f1a91092270d15c16a5a143bd0a0fbf26cbfd34718173fa19e466c9894d3276bf0c887b09b77a584fe80e0134bccf5c3bba566686c79dce66e554bd9229c74d4c02831f86142932a1dd449fb920ef675af899db8b99e758aeb3b32b0474316db13c9ab2665e651242bdd2b696c6a2f65304ec643808308934f727e3bd4d1e04fa5f52a452dbe966f7eab1ddff16950f211034ef755e1fbfc924f44f1e5b91c38ddc9cf755204c4f5de26b59a253b6c940fecf5db125d5d604a10e4384a0cdcceaa0ea4d4e580753b4acaef25a77b7455dcadf0f5bc10f948027062cbeb5ee2094e01374bad834af4805b98cf21f2b99fecb7b09827fcc295867d083b7696e42c2ffacc5ffb5d26088c468b1da4c967c97bd91bfcc5792cf18b66e5def3ee01e7e251c0796179ee3a38cbcdb656a3c6e4e1a970259b2d2e2dfc25e0b7d7229f5b144c24129d1ebc2e9e64875b298f9c36dcebc1d43e451105b16d20839f7e6fa47ed7076b603b5e17e78f979d01d5245c084e500deb96e6ade4d3fa2837cb400c02943dca4ec02b1367232f5ee56e70d7302195c2b6f9c0a213895030857bf8353c0a0d0275d0216c47f6b0cfb54471c6eb897689a64a5fc2d5b51f6be93b7ee0cf31baff1a5143a274779299a6b903f44f8018c5729cd8617919a13daac169683258a8340014d54f1e9cd82134eaab14c7719eedd6089da30a04e1d873b683316bd64698c81a6ca28ccdfbfcd69edabdc03da3bc84d51d770c806cb53597e8db6cfe2ece1df088f1aa6ba75319ebb27f9208674b19783da8d4d94653ea7a0ad7eeb0ade84db5ac471db947ed77c8b11de5ed23282e75360cb3969cb13597d66d041c3efd7acec993fe14fc6fe536dc5c2a6d0f0a787df072c2559f824ec077059b218541c995a030769896bd619b0e66240ef244c8b3aaf0e3f79abccc4a69387d2cfa3131b45ad4c4817d478cb7cb7264aa8dd46e5ef2d3712e3dfe91e615a321433daee0bbf20afc7051d3a5404dc66f2a02bb8fecdd280718712010115be7131d09737677293c635bca6ad085a8f8c159d772bd52c80dcc62e27db799b81d84e337424a8d8905d53adc68c8a222b6970eb8078d796b64b172965f55ba5c90c0fcb006865d7b1f0745e1458b1ab75c54380b3747da09ee3543a013e0b807158c9afbffecfa5a3acfeb185f3334d3ee923edabff723157c671330ecc64633a90347ddd77be425713b6c0f9b41a9789136c1ab74248afce4f0f569fc181cfc34aacaf3f1a4f7e8e84091a3a0849d87f3b8a7c6ad4afb7d357eaa0a2c915beeee2f1c6860ef3fc5f4cf0bf43c1d596b2c84a89b87d36c2dbd143dcbefe0bee5dfa04b7111895c8e2d9803d57270b347374c7a6e83957145d00e801db52df1fc37bd8e8eafe7a6c5b75a8c8fe32b6b2cf0e33aa6e7c4b559d2687cfd3e89cb9316ba05facd121f0921726adf89cc2094da9fe3f296305d700479a6ee3da724a39ba0f5990691436abb03e6813c4071913cbf3e70c6549589aeae288212d2257077c434f306c611b932c754d022bb3d40d91fe0479a9a250eb4689e118def6cfa516312c4ff022d1619c5aaa535e996af16016e670fc5931fdddd9e5d6105c385239a30e61c8d9dbe1185fa13b375f214965cca489d186a84e5eef189243212eeb570109c544fc8aeb4fd13227055878a15a723b70a27c8c902bd8f1c3f9d8865fb2dcc554f2d9c0e9231e691b1712ef052a9953daa36823151c86c2e1c43def615f4eacb610ff684957f08e58f9b07c633e0c71ce838bb8c742e0ecb301af85b4000b61e3b2f824e6fb283d310c69623c3b78e34e85f2c5a319b3e30649bdf982183702a4b3adef8844d960ca80ee90ac92237cfd5a67475241f0d8fd558df07dfb952fc54219fee76946c2d3cc498dc85b0b04b1d6b121d6210d5c97e1f75bfc1eeb7ca62feedb10f4c0384c771b331b230e951fb15ee5c5d6a2adff8a508cef25c6f7ba717a116b2fa8cd18e75fa5c711e036cd1c609dd5fb6f26c9f135bc214c13691d27c9624f711e6581a36270aa27ab4a2afcf84383170069a8c8eb7d9c8e86d328cb5eb95c81f3b5fd0738ab4f44fb0c71f543e66febcd8f4157ad4235feeec30fd3e4cf9e0967f34015bf5bb12a15fc46ef5d0af50e3ccf810ac4310fce50ea1fda53d52dd14fe8795645032c4976591123b74e263797cbc7e41af7be9b56a2195b4813a1d3438d83e3b4da2421746cd97f92176ed9eeb1ea29cb5a0b1629819bd7e7d40c963e629960607aaf96c2a3e93a9f52a37eab47b8c7611b61d5a1b9fe3d8cddb7acdc04d000286b7d8e09e8ae4e58fef9bf71ff76600bfd9c0a7f40a69d58c76459436959d916e88ad288fb4e82a3586b79fcd67f66b2711dfc0d9d140cc22c0a40f6fe46d09c12caaf56a45a7065663d879e8e6f12aa05e9265b16ce1aa2513aece0ecd83d15133f69a7c91fe0fd44eac29b22658d3eb16bbafd2e11647f0e1f7ce67168f5d3e2b45843defd6a4fd8ba901fb4950edd98a4e41b1bdeb1581c44694804ea07544c2220aef5c3f3d58f7d053815d280a202629dc6a45a931c7d86bc8256575d58cfb1bbadc473455fc22a7fd94b229cdb8ff4f8510c126887593f62040ded2894fb7f53665adb2467951efad062d30adad1c9c5daefaaa5748c614991887cb87b421970b6c061e55bcb2e2ad0dfa3c17e869b43ac272b04fcdf4fe29baedf3bb3ab6ad1a22bac0188ee3712d3db309e57efe5fc9b60c3b4fd2bdf287bbe16e88b3822f45868872a99b78265fc5f2c123e7520411ebb2c65652d01a0e2fea8e7cee2a7f667733e208f20a0ef5c845621cf4c2393f360f0f7a0b32d6b1621cbb8366c89ef90cf20919a6c9f5dff89803a50cd281720bfe75c7cd6e25d12938f43596e5ac23c948bf73b05e4e48b0135d1f3c59e93c140cda00463868dfecc077edad546cb99a54348104dd60886874cd680a38e74f515f3e1612a42bbaae442a80bb3af176a73b24d929825955bf33a1541f62cf4a00b7adfb0c7f20442213bf4a531718c245f8885b306fedbbe723cc33a1dc27c52052c4755ce2a302a412955173941c109f52901528739c58dfae6047d04845294d8ead6f94f06e33e96ed95222b1eca8068570aeae6afb5ee3d5d93302b114a815afa5e5ed4202a9bb3ef0ef373385692645bf4aa5b0192cb2834488ac105aefa23b4fa03fec0319b0565916791b50ac339942cd34e875354c27757f4a4aca0c4f0f2fdbb06869f4ce5e1c8cef81791f2280b42bc2d6884050d431bda7a93d2a0e77e72485bef53c70965e7f5cc599d48b7e00e5bf1f5c9f4ede54e56bbdd4ef28d7ec127c0e9439b09ca7f568e18b234943ad6991d71911e2070942517089d2eaff1f4e6e7dbec1ca498f99b7d4e0edfd191b40555babf8075eb5f2fbfd0000000000000000000000000000000000000910181f2425", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 40, - "comment": "signature that takes 20 iteration(s)", - "msg": "1305000000000000000000000000000000000000000000000000000000000000", - "sig": "0e0e0793a9f00d1014ac745f73ee18458e19dc0c9a82d62c4f7c5f08cb302f270648d108b2a87a51c5b83e6aa54f4b40531f01bdf4f59315cfb96fe20a21bffe3ccb5aa55050ab5ae428308e9f1a95ce546b09b68d9a3036a04c71ff617dc48b4a3a732b4b688389a8249a7ff14a35d52b6c96cb0a6d049054de0f7ad08669b82f94745cb89798d86fdc0c2375303f5849c8992400889cf61ecbf63bb5343664f6f63854d3518f5a63fa55098b33943fa5642745b0a907c8af07685a18d9af65b121e90e7fd0c0cf62ed87b09eba0f06559ef813649a08a03c0819da5479dee4d170c17c11a119b6d9055151bfda6ec850b70939167b4d4d5bedf4e5aa19c380b3f87b45ca8b71dd9007450213ff67338a2631b83ef73499c4cbcb8ac6210f836e73605eebb09bb911f63f8dac03570c245b1826ea4ffed10e7d6934fe1d2e5358d52f18329259c05b1e570528e7bd160435a826e39781c8d3ce0b933d3ae34c33c09c6a4e535e3f0678c27e4da154ebb05039d3775a3bf948f579e8920b12b2a50430694fbdecb7ae7563631776e7b5aa3d889b3071964417eabd2bbc3fa551e28fd49abed8fe37326770db6168813903a4b1f4a149cdfaf2e49d88925a6ccecb85aeecaeccbeb94aea175fdc4eff8eb6cf0ac7cfa2897c74bf6c1bc5daa283398b86416be811bd6dde7558bdbc5853752f2651369d3b142394fdbafc1f2f8d1139df065fa16df69bdc9acd8497a89f037cc6cb6eae90292c7bc8f1ef5d89a07ad877334c53b80419f864031f78be57a82bd89d523126e9161a1a5d126e52cdc94831d68cb1907545c0c619bfa1b7246aa50355591217018b7227447a7d17b28324fa6c7ffa1f5a119bde3eebd11dbed6bd9d8ad95b4e1d7b4d673fd35cdc96631e1a86dabd6bb7b66ad5985bca8888d5e8e145a5b5f48953bead5702180a99b9402a5658a7e7929344fcbfb574beea901367a3dd8ea90a75b54b08c391d5ea6373ea8bd10cfc563733c4f533f30ba31d3c0e49e4a5e5c91d45d4d638712aa80892a2a0c5922edcfee867e2fbb7f18aa032c774e9cdbfa59b1c27baa14e932f59631afa69caba7855bd3746a12888d5a1e64271242dacb972cc82bdcc64ec4a2c146306f39115d5c824b71c93b5833020985ca099a4e937aa527bda8e69324005462f5f8431d5bb11bca9e4c59e5b14096cea9e40a540546efa18e1364c4f1ee855cc8cc564dce2ab8dd683bd9804b11d02a1f510ac98c120b6ba64cce16b203e53ea3d1bc69bec0d06a17b30639cd9b24fd1598e92890e88f7dd1397445db54ad8df5e136ee60f22ac090f2bd905765e810f54711f01c63564ef90cb01108b2c2bf1a6fb5fb8078d609117e111604a1d927fd24c18354ddc006f286975be3bf1ce5593715a8cc873c820f778e9a428e08fa3db1a5f52fab22ef5d16056092a6b1da23e3c64f205b3490f0460e9aebf80a4fe9acd31e5747431065f575637c8c4cbc5dadc2753b90e69722182a344d3b154bf35da62c1fd0e98921559f7d6010fcea31a79d36bd763cee1b2855dd05b44b36c4301cf6070408f02689bc75ffe264f55cbe06886019797b3ce3206654ad4995628eeec2db47a2bcd5feceb2f3cd3246bf162cfeaaec8abbd63b2e6cc441b908a3301c860a3a15c1b9253cdff625fcb6de85ab78bd802dc5e073a0cdcab0512a076427d7fae7b663d9b81bff8f0192fa7db81dc454f32340e200ba59bae4eab701662ca6453c233be851cde64c0a966ffc6012681dbc407c02073b9890781c8f484c295720eadf934c73e2b412b484ce4bd599a7b8718088c55433ff1a78072188e289ade5861bdcda6d10dc5c40f1c189ad96eb188bb46741e5ab956214046c2db868c8e019ef5a37d90b92fce70ae8e4a5339f612c0b8eb43c61c0c63f3a59edbe6752d05ecdc178a8a90059d6fa7e0da0bbb7984b7cc1ab8045095558ee505b3ddc1b3db2a78494436aa9334f6b3b3896d33e556e8e2b9bf728b5c53c204a964a697da252a73b8c120b363923aef38f993a3db4c24c9a4b1f10f444be9f87677df5ff2c26e419bf9c2f8e53ea2e6f1bbbdf2b6c5090dba385a5cf5652f9929295eaafcaf282826305ec5766fbb03ce153b32d49aa7a66752a772d2091568f1b6afec5e53dc2d5f73eda96834404bfe58fa5aa692f266d0383ddfe12da56a61f93933b6794af38ee9e31c3721c1bd52a6690bfa68948ba8d6577ae6acb3d5adef9091fbb7d4007aa8b96a7d17cd58987525296682fc777111ea979c9f3b893fef381c03319d7c6b9d4d523a0e5b98953830e46f1bafc94aa6c4c323d2a8a76ed1364caab808dd7eec175eb230de35e8d6f4ecd0dcf32ac6b1be9d7d6ac740f458ae7530a64baee19357ce5a3f106841d99935d1606d4ca7edd2d5da69594770eb86827ca9180713ec4df96de4857323333dcc4c3497e089ba6388a39450d251f39a1d2d6c1d6befebb7111189bea14c0ebb75b1c64eadc76d8713ab2290a7402e86c16ec2eca769febb9d8cdffa530eeb75854b08c52f69c1bff47c2f775353484527f2e3f37171d3fb44553cd6dd4d79e81574d01a6d4924d7b2dda910f438eb4c7ec938e5211ff4200305fc3e9659f8d52bcd49d5ef6ff5125d1f8096107ee01633e32f159ef17e1343af03076061b13bb3b25d4422f21b616393cd2d36ddcf96598c1d3f6b4e29258c94ffeb07410d1294c754f25131f68b4018ea155a1c800df5913cbb5c7520c7e33c3adb8e21fbc692b9d4ae00ce6e06df53cd3c13b1d12dff0607c423d41bdd53f4a632a2b80937ea64605e49c9694cb68e3f82fbb164964863c9d58debe663db1ec93382b8149cba27be1c79b2ec53396421a0251f3c4fd3199ea45c944e250d9402128369ff9d7fa48b0dca0c945eeba9b90539f3d4207b00d86687418dea895a4d467fd7e48fd6edade5d06434b9b1b82ebc0110b24bcf0bd4c58f9d7e5121c5863708b0382838423fcd9105e6776dcff3e914c5c425b85b9a1c5ee805d28925f313931a500e5bed7a4be914ea3a1a87e8b798702d45c6961afca988059bd23f04c38a0f4c3e9d59eecf1fb1d07ab1cb41b472b8848e5a149226966d540b095c23b293d982682dcefb8ee426ccabb3a5ffa070e019de02aa3f4fad228420f27a07cef98fe7cbdc676476ace8e45a8be1e282c136189d11df419053eea59288a16e0708b1124535a2a9d42e5ff42d514d05f344d75d26abbc2435c42daecf028c60621061565f6fd5787d74ef09ba4e1dd3f4043f0a6164d82c1c8a56971eb1ca21a966f80f67bfe32c2b3bf34e680a5abb3279c8e7c71130c77337d439fdee9f0589c268bf2b116eed8c6042e3def0986ede75a7ddb046be0cb9c2f5982485fd18bfd4af6649c73724b9c2046de6eab8c12ed5b1c56662b52d45eddfc9441f88d6dab41afa2c351c4779f623a6b3e4f8de8a749de2ba28447994c57566178c29cfe2d927d7be251b9945583e0d62591acd43c664cf8e52a9f96b08bdb914e5cd40aec4d9ee49088be114d7f1c326622262b9437d4ff41ab766fd164cdbb831023e7b8a4c2f215e9d412ead4176445c5661affeda6bfd4ee4d0f39304ecc8db068496674f89d5be493a4e225239c0dfa31b8ffb4a71b71548ccc1cd8adbece95d2cd76e2f951f6862aa265542696a0d78acf0bce2e20cbd1afd6339f33ca27efd6289ace29fecbf43beace6395634e3cf6ae7d207f31058739eb878cea44af09d18d0100c719241948dbb25943f8426d70c76011a6655e47eab980ea419c0baf21bf3c1cd08a6b56a95cc7ecc803bcc6caefde0603267954cf865423437f3af6c3d229382d4e6e4ec8699ac7929dfa22dfacda6846c632c8006c0f1c7bdda56b9acb231a52a532b2c5ec3791b3c3b7c7e507b9d0a271afcd983474ee55e56fe4e7cd8a0bc6e5756f118c513c9049257bb7251038866517c4c00be889772e7d42995686cfbcdd5f343fd3f41ec7162b61006e55eea57837c0739c8bf2fab9d24590edc3622d2b1c472a1c9a5a4dc63a883834a431f976f1fac01254c5c319cb4da867d129f007a4dbeb5626a9f53ce8db7044bb5e1d4f974a0cca9cf955ec1561b8d0afbaa14988f6d14c705adf6c87bd3f7416611867a61fa33368a20bd19f295c40858d9d0946e3da6771c41ca3b23bb97659ad5f5ca6f48342c323889bc3f00fa116b9eee79af395b24eafb213bb3f74d2ba57975564bd14bfbb97bd824f5ab3996bcfe3d3728e6d2fa65aff6ec874aa468d297f4cfd36fa55f7c9e9d8ce610ff1c36aa2c5b596b017495e298df6e199a6746093be6b4ed0737e834fcaafb52d9a0c37a82d4afb0fc19d81d577ad451edce943112aafae8417e29de50541ec0a0cba83ebb61102cb9aaee51886fa5b46f32f43a3a6caf58201d09466577619b369986a3af1d5ebaa1c0fdb699328cbc95879205b3f519cc235026420a163dd96e0829ec098bee25386a90971477cb12c4db6bf7f48f032e631f106441e34450866ac7e547f3cb76a0452d1c305b3cc822942b5ca815bca6adcf267d8afe7763fcc8b70e4c31999edf5bd25d42793dccd212193bd4e808373b3c99b7b81219aeb4d9dbe5ef0c16455573858cb8bc0454a7eaf7172385cde500000000000000000000000000000000050c141d2227", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 41, - "comment": "signature that takes 21 iteration(s)", - "msg": "8d00000000000000000000000000000000000000000000000000000000000000", - "sig": "bb8a458fc151be6dd575d810ee1dbc1b0a0c0fba3b64d9282b33e80531e9cceebdd7f266d7d810d0e4ed65a2fcf188c79d0f8b72fb7942431510ed1a9a0dc5dc53783911ff8e486ba22a0789a685370bc44dffea387de0bfe7e610b769b3b701f8c544ca3d53df14e0795927558ecda480cd7ba8c0d19cbf954e032b253289c42c657cc18ff7d5ebcfd4ff5163e8a36f585ba1409f1f8f039f87b1ddd18170048a08e4366a19439bccde7bc9d220642eb94896f4a64b1bc3631089f71ed0be13b4a38c092cc5999ca9c4cf4a4bab102f26599f651133f51cb2f1df9f6bb7b9de9b4899a38d26b9c6ecb29efedb2038bb92e2ae3401d97f3ad3e1bca5601b3f897a2ea831e6a046a66c69a7da9c1e256da45ca11d4d63d3d5d9de9470c117a4f62f3774fc9c919a73f06fa9e27c440dd94aa19d52de6e53c5f500821fae286fea255486434930a444ad90a9eefd79bf9e335a995d652c7f335d09f7519354f01dab9c10d292dceded1c0db39591544a4045cc7d3d28e4da6be59760ee7a74e312e482ddac340f6c6f4e09db4df3b53052fdecc96dc7aa6d6bc160b991099f0aa81ac1982188245dd1d8b111186377f2f617647ecbae26f321aff3931188d2df051f3a4296e406790514a33080fddc43ea4418d44e8f3fae0660748ca4ab61aaaa58a6e2fb56b8ed389b44afdd63243bb592e0d531d79e75d396a007da95535df0ae74d9fe6b61f997811e3934150f4ce8aa292a0fa59f66c5141e3bb339eec3587b86be94b765aba9f2362ba607bac1ba18917ab7b15f3e3cc2270109ec0bec9d53fda5c276841d41f29f91db419fe91b7d5a2f04c5322a15f552514ab592ef54b59539fdf2fc66617f5baf1ac054da64f9064b43392d2d14823082151ae5f8ab536467543ed5cac30eea35904b4a737a11f53fdff7a5099e915b1835aa32ae57e0a14a781966d17ffc4b66c62dc4f35fd414ae0a22719241e863b60ba63e82e2b16dba8672fe7ce565007e8ab53687561c8c41dbd736fb8881c5fae17a28cab7c1b2483a2ae932b55e5b154d05b66c3b6db45a7049b5934ee5880471c3a63321b193c642e6ebe89c54f6e60f819dab75c4838eb6ca1ee80416dfba41e7836f3f2361fd4bfacd3102c1f28ec517ca8db5b38ae3f48f502229f2144750d5d93e4c8125168ef9ac066fab91c295d47e04a01d30f1cc7889e9f9911a1ba9b6d44014637217571f2e7bd371775611c00d651dd5fecdf342e8370a303dc7e4e936dccefe0c66a8d12912ce2fac1f99b45a5fba11a942fe927005ae7e9453fef8a926fb6c8c3c90d6ab39bda85dfe50ab95541c71d4aa5debe9b9a10b92f74f24d09341738e83fa7687bb97054f20bbad10ca1ca2f88a2d9f51fe9e940680785181fce68693727c4a39c57a108f37e41d35efc7e8249f60eb05a68c8b14913a85be41ae96e8b28a9f97541643657f13d6823535edf8ddbba95ea0768d98bdd126f9829025b799842e2b58be73022e16cf46b0160bbb93f97e80ca5b7b4c2581c3be3d7bfcd81a2399afac6e6388a9707d7fd7e1b19a56c786344195a89da97108c2b103ee87172be50943de28d95cb76722c070ce96383b4bfc1958162b1a066faa9d880dffb4b6c4a864b0461b085eff9dbdecd2a2643b1390bc3d5f00830e6e43aecfbd3b762ec023f2c684407e9928ffda93df2082231172f42f5b887f49454e1ef973275a865950259afe4d3b9dd5fc1d14f07093248364c37db8bab873070fb4720130095eb7e1afe4899ff806ad9ac19c09387157a560a98d1a68a1f0665087377f5e17477279c094ada07321760177c3261b9042c36c42060b700316a93450cf8dd280a0f3455ac8c1e0de4bc40aa0af63857efc77023077e7f16a805e909dcb2a9e60a43e7d5d22fe30f8f8a8291c79a2c08a8b5c3bc9dac5402e6e3bf87898496511be0483e9e11c69b6356740bf8cdc075f3a38f9d489ef3b7f88d51734c8bce0acf6fb5beb7a3ffded49ddf0bf54d6958f4276421bcfa666c273f3a415ff69ca61b736eed168bb3795f9ce647cbd413b027e520e22ebc1500671bb11f056b3b41865690ffccac3718a597e16b217eac9b4fe268520a5d342f1de7817c3568e6249d9f4f014dea7b90730dd06ae4acab0a5e598fbe72b30fac6355068a74d8b311348210822d6f8409e77806a259fe4eedcb5934d2e09f06f2fe82274c942058861d5449e6eb923ac947d06806a1f812b6e4ae2e0a929aa244779c075d7b4cb9edcc664679b6be833c81d5c688517eff2d10eaab41f93e48b7961cfabb5b9f087f5f9ceba4dd8d1aedadcf5719beaf1ea95398634ba3cdae50ebe9e46928f4a2fd153d38ea9af1cf2e7b832c19712ec57dfb516507dd3b12ae1eb82035c1e3347ab97c7868142c68493756493fa571abe71c635b928935eb50cee1c25a9bd60e88258dc777dbd7f96e751f1bde620940d8659730a4734c77402b7664d5cf6d8c562d64284c637456dbccdef87b25e96c21f9962eeceafe99a9d6199cf846a3798fdd09997ee81cbac964ee68bb34b29d9dda00f251f7e2311bc1b6d4beec8bd4d3035a82285c2288a90a216a355e3d1064943649e5fc46011dd1ed2fb9289997afe982093619a6f72d4a6b6093e1303ee88c74721e4bc7ea6289f437cdbb9ed0a6cffa5d7d918368b986e070c3dccb55b1970457d189f9b59ab8e963e5e8337292d4c71445ca44241f9696d1ce3910804fe7df2dcf5854fb9116f96a1a8652c8a7f2c1ad07b07b1da41a21148bb9b24e8d59dd023e58470a188453c4cd9ca7022520ddc6c53f64a5ba9b3563a7d59ad317745a226f7f0d1af6f71a5e1816c71e12aef1e8a60eb67c4c6371a191a1199424cca295a9ecec99bebdd1d386e955fe0d4b4e7b853100f17e09d5e12c8ff569e67bb7d118759ebfcd8c1e954a6cc351c39393ace4d531b42e8aefcb533020169991231d525bcaffe20615d0adf79f258d7b3f7872e1c39d2ab3c616ce79ad8054f0c55241ce148437818aa8419231d72453dd1fc28790b724fa49dc41e43b838d83d8e6978da66038258008e72e3009ebaea2624af497309d9dfbe809a97a67ffe71e68da7550f12ce66e333a7196f5402dbfc35cf9c021b8150c91b535b76f3f6cf2925e2b5c7dc9318a34184bf1e84b06d8edf792f8a62845c0e4a47e5af5327353256a164b167a895b6617a503de6eaa46f1be6a736b4a5c81eab9a6c7c7e78855b44d9dd673f91307977545341926d8444480a44da1f7a38cc85d266e0b43896db4e8df8f87ca1994160090884d417eced5ceef498f3d86bc482e6787ba9fd9f95fa451a9e49ca51e72453802937b2e1817daab14b6140e1d12d4c2cb07567fcbf4d7deffb0ae80859ff3c3e07f7494e16671ff2c2eeb921c52fe21891ec58042bfbd247d6576da111a7b40d0d68d7a66abfc133b55912df8f85fe06985cf91dfec0c6cefdd646ab64b30abc9f402e39f246ca3b90f9b3c7791443967fc31c15bc38a256661125082ce326d61ba7b9ba49614cc584507cd974baefcdce6564a0332deff73db28129a79b28883878e738551107e255a719aa10f5a71bb8ed70d053c7a0f64ff47ce85239bd8965dde32e87720a5661756d2bb890e0485bd3ae22f4f030a9c76da63fe0d27146f16fb02109dd247a763c74359f0ec63dcfd7146eb747e15be6a7be46b30b1c7e91645926122674a722cd920d925999a9d2bc293627b5395143769c26e544e87eb076124d4bfed589f9a0b5cca4a7f52f16da6cb35e3956cf758d0848a6715ec8c3abed15026d40ba323940f85348c6c7759c5d7fd0c309ae46e75fe76042f2bc3884afb8972f87f3f11bd1815b39869c1ba5f4e35569786839c792c7149fcba176623566d29ab1dc29f3bf2d374f24eee794e2003af92a90b06a5ca67b5ccc7916e9aaff10ff1387b72d72f6edf6b450ec2a47a21311f9b4b0edcd468c43c53b7e6a233ce134512ebc742b9e59f8be7e7605f2df5fed2ed705e679cea3fac404eeaafd03b0345764aa821a40ba383d696be7749c5d35ea43519b789c06f316ccb7fa468f5562f688906442c8dc36d3997e51c14353e6022cc2b882e8296ea274808bb87ae9e62c307c65cbf30ddfb2453497d58075c2c4e6034dd8261032924750fcffcc5fdffade784907d7ef657978136ab2fa29ad20c9c83c3e348a408c5065911fe61e0c439a1d7ef058116934f6497d96dc661f8ba21fc255c021c7b52b6aeb0f1d2d219ae131ab0e0bd01967698b63b859c14b3252a7204da5cdab7bd2f78c6cb639f024c92465635a41d115ea6d042f3722d605e7be2e868909183525ca088719876ffb987afa2f0bc147026e1863c528562619ee551c64380ca2d8c315803a4098f3657d982397be8262f7d34ff4c05f45b6b0eef3d7c13fe542c851509e08b9fcbd9e48d1ec72c790cbdb9dac3fb8c7a57c8a9e2eb14ea840e309579b0d04096ae896ba2f3e45af7939dfa922b96d4b76da3c3b992cb72ed55c2a424f371e020fca507058ca189294a772db81e05f33a50282c689cecdf4c28df5e17bf6cee74be67ab96d7fe26cb1d3a0333145557a9db5e4257b1977bdf7fb41496b74758c94d2f7154d5bdd0e2c4a4c7581e600000000000000000000000000000000000000000007090e171b22", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 42, - "comment": "signature that takes 22 iteration(s)", - "msg": "7d00000000000000000000000000000000000000000000000000000000000000", - "sig": "7b2fab305f92793314f5aea42c8544b5a0af4ceb7fe57f194c66778c320257377aee97acd7b9fba4c8fe18cb462792452d44c507f7840af2c6380d1a25254ab0874ff347626511b93723bf76abb608ebb0fc056b453473b1d2c6d7264f0f2712ead95ee34fd8f620925a36decbf3097ae92f04dc9981e1cb96da9fca9fcbb41b64fbb617a21b17b37661ec5bc538f00a1acc07aa667482daef1055dde874d59b14327dea97ad4f97fb1430972ac82360e9fa070c9b3ec2545037cce1dabe34c274c1894add81507268721c2769f19fe089178b400e55822981c2f8b9f51f96c48d83ac24ff55ed8f5a0645d122f1c17da2bc8da50cf1914d2900b1389ab9f1a00b6253a67bf907641ca5385b49a07ad3ea0b37e458e6caf5b4dacc7c74dcff22ba677f23ffb64e9c1e2edbee99e7c73207d3f288d2285a7c0e14c3b2ddfca88df6934acba9857083a131d50c88d8f8ee8d24304e5610dc53574b8d14198fa008435d33d03c42e377ae3c627190a1c6a1639ddd98ac90b6b6d0bf7a50672000e0d09898f21c705c9a5de142e9be15c0c0f9b06347f61a0ae9741aafce0c418ffc1908c8c20b68be48a6d5c8f5c0762932ab3e73a284ee039123c2b9406751ab6cac8c610b2aaafdfe539dfdc1e800269a0a1fbde3b5bb03cd938dd08160fb8f236724674d016a76d24832f4857bcaf7faa8daee394ea5d97cc12c6de62081050c0d0f46b10a456ddcd12e352f9fc5a9776087fc6d16341e0346eca5cfb3ded070e278146b987ffcc9d56396fa970d22a20491ebafc95ce00f5b6d8ead65868bcb6dd6f31bb2a9d85b7951f9ce8a8f7bd7da2753e54362c8981ee4714afdf398dc258f3f0e485db710f0393c60a301ab97d801c7f268385f5200e6bfbafaa69ccd87fc1eb0c29a2c6f73820d6b5f561ad3659e7b895a9ca7798422a673594ddbdcd17abab2afa6b7f5d5c0236b33b3b8e6129d9a40ed534bd158d436bc3279c769abb3bcf4ad5c4e864f2461915266ad45b7bdd91023a09e1b3b2700d8294472e1b4a40bb1a57844183f80dac369ef701a0bdf2290f3283a681dc432b396451f79853359ba9df78e8a6fe6a1ec4017405efc4a78199e3365854a1c94ae7affec9682d1451d1a219c9b9b17ee6726281c025479e2dd64f835ae15aa2da8c38f4f07b014b0e71e88a60b95999f77aaf33a64cf6bcb1bb93bb151b1762dcabd12201a5a1e7df878b0c1055c2c263bb10952648e1429839fd180c173c6270f7a0c43c7d1c0bcadf81c0400f1d8355b7d0983802878d36ca0dd0c251477c12cef09f764cb261e171c1d8052491e7dd0cbc3c2801a06d7cf6a67d55c3f9633a8a2d74a1bf49905d29c7f574d2a2039f41835dd6f7880f3dae8b60488580975d9b19d1c2d5b64f91f01b22caace58142ada05cf6bee8e6903362c18296195b1177b1aba590e9865d4df042a33930180fb4a99a7e0ec262a38f739c098e9b48f8a6033434bd506e68c46fa0a0e9dcf7562e27b48e450c71e33602200192fa91828ac40854f33ecfe8ebb0aae4ff1dc951c3ee248783650d9e4a56e7d913e5903abc845b970397d8ce6666f410505336e7b906ba63e77470900397451a8528ff8c376a70403a4300f80b5573921f29ff90728286022f6ea62f28e9b6884f1c6e9d07b3d20ac2b281596ba6a2730b9cf447cefcd72bbf8f95ec88d0565e711c286a8c269ae9ceb287ef6e6d00502a8a89c766a8c39d93c3bcb654a07acbf75c7ec12b8c1c494b55f9a41195d3fd5e19bb4d93cbc16ca4f05be0a86a9aa8994d12584be162cc4d71fa629186af1e3d3b74e5c905c8be923dda76b87071e84883da2585f2afa64f0955434a53f0c0cd63761291c88a4271656e3083982e9360e0b76e18f6fea30736cf97f59256b5739faf5e87c51bc76a8fd06b4a8563a11a3f2466249beb3eb8fb8fe8a3d0b9f06484f6fdbffd9aa7919188b626e8310f9d1c83392ead724185c62bd1b2ceab020cd305c4abf081bb3984cb50c1cdf7c59456c96f91016e9ad32c2d47c67218db359248da09fb14feeaf6bb343319633e7869d6103571bb5b587256eaf4551d5aa74860ff266f57e55f8c65a2ad87aa938b7f156f2022b62282a0cd4173dc090c5a74aa5702e50be4495258c509d22ed34d63622b62c0dfe1f53464325280281a95a2c273e17319dec4ccac46f31d953743e03bf22f40b0fff77409072dfe82876d9d45a11dc0f1d64010ef32d57eb60a5288b089ec9d02bfbfca6197eae336363bba37435e1e558178613807da640fddb0ef205d7c91ec186b397bfbfa10d588235013aab3ad21744a5957def19bb7bb7cd4f676b23c7bf87579ae2a5fc8c0cab31d72079a4d0cd69944564252f9603b508f5a83e19f09c704c574066617e8b6fabe690e85d92dcac354a435319a93cc2fdf3010c52e38d6799381e8cc861d69db0ca8defb5f8b1c017dda46ca9302d8cc1d3b1ede0c9dd63349bf6011050c968ca3f3011109314dc9655d1a30f198cc84bf12c812e90939d7f4075e32697dfd2cf6d17589494e775ca982952b61f8b99a84967a431deb64ef7ec9e882cc761c8bc66f7de4006eeb13f9b6ff2d92db458ffeef5b2cced63172c0f4764da145115b615cb6c0388b6e93aea63de74bff64fe40dbaac7769981bb9655de32a881ada616e96cdb74579a0065bce2da90b64a813d57abc8f6543310065cafbbea9512355cb3f058b35bcd357bde9f55fea564a6b14bb341c6c755d4dd5a72ac79d855fe50aff80d683530ee563249d0d65f64debcb24962c61ba05c5f811b9e0f4e5942797c24d2b08a4592d590cb871272f5c1228e9988955ca4f990ab2b138cbd33646772767d4f76e8725377818ff1cf03c01fe64bdf05e61a1798c0cf3b4b69b1df9f756ffea314fadd17a6c6ded6765d59b22e449ba8c78b1f8f7b717de8a4462b02d1bf22f24e821888946f309c7e60115049997f0a98e5f04613acb46b5e231da31c482c25e7eac53f09df009728675e07cc3b33a0b0c6e9199664a00c8236a3a9ec9d6d5aa2e9317da6efc75e03d95d4747d51767485c4ef9fd438b767265093bb8340119f94367b506796bbb6ef67dce782d879a3673c0e8415c6b55c4faa3556c7c823879ebec0694dd0783ab8f5a60ae10d1c3c42e309163bdadd31aea4869a673eaf797138e332df0579567ab7e0d1e72820de3e7068ac2ee207794ed41737dd698f3d9884bf3d8f37981406d856a4ad5a6862df70400fbfb719acbcb0fd6bdf6d7c4ab3aa10bc8d6d7452fb9546845ce1478ec9804b3fc0b64e2a292a2b1e244a3601fab84d082eae74f635aaab4b5c1e6c342a695f6804238887ace79dd8dc63c2266d259eafd2fd876517ed9fab048444a61da824c0c836977a82591e1f7a813b0898863c2566a3651c0570821ee974c4d031ea7df06264d1616d48bf6b2ba17be39cb363843b06c78d112c76cde5cd8495c52019359f4aabfbff771acbb91bf97a5acb1d46d2e721f78695b8a66a145c15bbbafc77e5070305b37e854eb16adec67495c35f44068ffd1ab55fcbced4c146055343dcd7bd366b604ef8775a9985a1bf0575482d162edad96ad645f186bd2bfb266c3b178f01729037d9b7ac8a77c518cb5f316c050edbeb0d90362e21d5dff7be1f8632ae42cd13f9d7071f0ee0ba5a1a50a77b05fe3f089f1ba56ff7746ef35ae7bfb16c2267118e203b75ac19b334200949f8db6dfea57e0599ebd3ab484bf5be07a1d1844aae9d63af81cfdfdf1fff686abd1093d27abdf2e92308ee6e3e15fe197e3a9bc6a9ca889e06cb73cf824363267d45095e8b71f84a9ca49c66ae58713edee540cc357a08a7b855efcbffd95f2b765fc9d7bfae809726c3632915a0af1cd1a01abc864a56539d5fbaa21f7a58f430164e81e65b90f453c15f83fb9236ca8f54fd2c7e50d0258e9a383444247301aa1b42c3215337098ed426bdfdcfb251b8ab08c35fb0570dd08ec68c1896a7ac95ba6da0437954fa029b03aae7c64de3ff3aeffe38ef8b208d9dffc62e32f44bb968518b9a0059cb2ea2e59b0c614b7787d0068ff7fb5bcf59ca605dedba63a34626261e7193e97e7e6c45f3956fb46c10e88a94b8c097cf2016f1c2f76a4db6568e038373a7f959c09ea1223c66a5fe011c241f206e03dcfa03964dca7bef53f1a442591706fceadafdc7fe0b1ce3a54a2e391e51555beb3a290c29bfd2d88f1bee4dce1c6357b4966fed12f61a8af8c90bdad34b8d9bb9d04df6c12b717ba937fff7875cd58ccb01c8573f4341fa3d3648cde127b6a9c4a7b09dfcf50f39bf44d1fd94f5da7d2fb1c2578b9c6ccf19b9920bc76d1b91513bd9088ec1e818898609ea9f5719e4b458b9ba28cd9dd43b0402774dba02f4e1e6e5c71b167caafadd9678932176710a41184ba19702e3c40663735a1811c56ea6817c99f20b5f9595855b46839cc64450acfc71cec14c5d56c2a799ac26569cf58a8d54b0f984828d379869cd8f5eda5d0867199c914402b016decf3e98a2e63948da228f29e6d52a9fad658997c1d3dae404179370ab68075e49868abb5d20fcd4641a83469bc20a288c93abb2ca105b6bcdfe0f122129303850e3f33f6189b2bc89dbe3ef000000000000000000000000000000000000000000000002090e171c20", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 43, - "comment": "signature that takes 23 iteration(s)", - "msg": "b900000000000000000000000000000000000000000000000000000000000000", - "sig": "c00dbc9431a2e5689d27b5a3f09c62fd6bf48550b9c6424db5c6027bc0b5cc8e9d29f05fb9d8f50a85d2c5d8b7a4f7f36813bddbf7caf8eff67a6c2e148890f9438a5ad85e6f4eaf6173f122dfd160a0ad5cbb091d08130677f196d22c8bb6793d174f71516d42bfdbb18fd9a371286d03ae41c7515adf78b0b9d0279538415f886a7818c6e09117ea092235cf18bcc834cc07de3a639c472d63cc2c42f6178a4c1fc61e5ec1fd5456851d586f37b59ffaf43e3887616136f8ae775063d5e24c137f63023d056ca2bdbc4f9e059a906fecffc72cbd6ff702f06429a66420bec5cf936c4d8f0e2f888c9b5bbe81644be03bfbbded0a1ac71b1e4c2c4df783d6d2621208f88c58dbcd947fb62ab972bc0865dd043528b9fa057c4e7a0f7cfcc2623d46745f4ef63b66aab5ae5999c625fb20da4f40d2112e53122707837501a0db379f262977c853083913030418cbb78a12bc6fb85857f401b7e9671eba59c1d11b55f83fcbcfad880c0d8492e03935341488bc7f1f77daac3972a028adcabc1b3f3ed7ac41a5caf911aaf8c76e0ea75c1f4ddd109a21e47c7a5fa2103dcb5e588c354d80feeb15c3495c9c0303f7d42e2a211dcb9b0600245b35448735877d6fe378b38aa279d81baa922b56693a2cfbde2efc23fdf80a78a8f50e9c587f2d63e29f0631633743664a83ad3a61ce12fcec36858714f399591229f7269023412b7cb3cebe64691d1c63a297859d10d12d221a43e37432da12c9c7965aa21bc82f7047ee6018095f0e832677d83f490b238f00e21251cbbad5a9aeddf11d4d4dcaeff0ff89caf1e8639ef0d26b31535c3fb73fb42a6c4c399882961a51ab5799109f58104abca73d8083c2a4b64ccbb9c1744b53d8c416bc902802abe8d7eb9a39405c91b61234ca7d35735e18e620067404d0226e7410f63c52a5ab4ae58281496d683b84e88055e970462b9d11b75688f8cb3dc47caa0ba1caa5106621bf59078ab30b113b4408d891e63eb7dd1db637607e6fe8b8b835b2205c5b17e7650a26ce59c3ba37a691a8efc35b847239fc7c60f61ffa06d3025855fd8e63f1cabff8d3f76f19ab3ebbae67786de70e9880887642259bc89d4bca52bd243b851b7e229ed4aa7170d24339d2e09ea779189921866a9bb773f09cf832b93c95b8846e2183f8e23b47a92d54af739dd9ff8cdcf13dd9fcf3eba396d3c76569b733aaa543051668cc436b2ff40a366284a0eae55246389268cab3d516b19e0d5184324fab0d0298872fff58af31cecbbf9b7abdc26509792483451da1cf5c53effb81b76b2cf28d0892de1cad6cd4ccf91496d64d31b9e8eea56cece8a99813ec49ff568c32763e3164b638ebae34852f8a827b781ba03f4d42297b5725c97f9a6e82668405f3b0c589ee7073121e07c7c39901e338685a5b1da04a127cc2301d4ca4685777ca9619f3cc3041a68c4d6034cf3d58dae42e61a65339885151f70c12eb9d32baf5d124bc9b47775b612e35965f99ac25b60bfa182b84188eafecf4e761b58be536d8c241a5df7cccf92bfb51a9f796521f6fa8ecaeb8574c28736d2e9a3e05aec22125b8ef6972cf5ea446737931e2b3c3c27dc3c84951fc60c89151082d222008a271888317c7fadcf621c115774038f21f89558111247a81f6f5e075577bca24d798cd66495e4f4eeb405488d0c39ca05e8d31619a5e65bb6b2d5b8e5683532e9475cbb65190a4abc6edf981a4de572ba400e6f200320cbcde65f64fe9cb8bb204faa9ed6cbd505b63aca60ade2ca9c79978bf0d971a8512c11e2f8bb9670984cdf29fc1a08c2e0f60cd4bd0630c0b3b34ab16f98e36e68a72841e34525bb5c7bdaae3c221e6d62c5b495166a9acd5fe878c766179c4ea5d88b3faeeb92bd0ff372de4f0b4f7e9002c097c2ff679c25467499b28912624de5252fa5d48014289e75a73b01021fe0f302e71342d525a53e754c4ae74c700bf187d004ca04c7bcbc956599976f70044fe70d22a0c82a3cc2a4aedb839f3c1a1d0ff61d815fd5cc74ff9c4eb40454ab6a53701913f176df2d57eec4457a98ed417c6e475d4fa068c6efcc2c6fa68bb80dc14d88d42d692e81e3b791955a2a4db7b9e0b2e959f4c4f04157ddf3f6b71f93e2768bbd25e807dd3a73f3db6641b373f1836782fa9da011c16cc5b6ffbd1fff811e23b1a3e0ab162c879369a13161010f5997ebe78fdb5754a34ec51fbadddd1f2afb927434175cb7060801c4ae80d4fbc8f9548381f6bd941e57bb617fa5d78ae28708e054a343b143dde9d5afafddb9181484cbf910d431dac96cf60670753ef1471db18911c4de0f14468376aebe23a37d7a661089e5487d9d3c5115a563f24267ae8fef4acd06105c7f2da0ef1691ae589105a45ca335c408e765395b2a3cfeeb3a3d6479780e38e7b52af3259cce9206f305e7842471c6ef555bf1d3fc6e0afe2b8ab769e2aae1b4b97339c273c051abf2b62ee283935f4253cfd1e855a2d549c3ed591838f423db0aa4ccdad5b14956e01e7afa729bc86a563030097bd6e446c990f83adfa5da4a2d71e42aac0256e8e48957f301a745733a5dcec0f761d7da4f5842c99016ae2d91eba8b29a9fc48ced59a08dcce4efa84acd21583442a24f444ee03c8611dcb108f1e9d8d6cb40330bc324831af3adb7585966f3312762d131ba54e45b2b695804196f3b1bd5a5a633429579cd18fc4dfbefd7c7c53873764d29c32938f25578ae0a7950c29934d9d878623640adfab823aea5b248348ed029d69a41f2762e3bb859fa62cbca757565e56759dd51501feda8f3be5468dea32f51d5503e9641e3bec3b755aa0fd6352a08254c1c95c5b65472717c486ed6e090ebaedd6eb4378e75bd71887f19bbca49ef148f913cbcd0725c5097cbd601e78a8746464e552c08127eeebaff5de1540b37b7b9dad95c74583eee8183504dc4d61d1b30d51e5a7d561173404d97b563693c17083bb3b055effcbf0b40e688ffb37f46d3a291ea0b54cef41f8f49464480b17f7017f7f6e9df2805f81fc056472e69cce7222b827b92c3fb1aef3bcaa6225d1e8c23e0cb173c2c2c936b43e89aa89886371119c3203b7cd3394e7bf29a0fbb64ae19d476f118dee4700a7ee400a73a07a8896a441614e3116f76cd58ae6e8b9bde7ec97ab8776e84c9dff4f41680fc306c026ee5caf39b58c3627477c19f3f39b3e35bd4695ca73d4080a80cda55be5d3dae4eeef8f24057f45b932fb6e58c965512d3bb07fdb87797ed007f675d0e89085d7eb93bda336692cfc211a289fc104a9fadca4b1de6db0e5868930ac571814e175cee5fa8db276ebfb1e51809584da93bfbdb0df3397ac9f4fe47ea2bc772c7de7006112cb218e5cbf402a923baedcfd9e4991a8cc03b860beffc9afdd8bf7265559c5af0f70c4372b1c24eb8d4126debb564780f7286aa17149697e7d9c327ca50babef283c6a991bcf8ac1fc83743a8ab4383cee0768c556c02194b1339f92bd1f1e4919585e74251ecb7defb768021156c7f096dabd1aee777774b5d2537957d1136bb457b7d37dbebd581a1b60c4402f25c273aebc1bcc9d2ac03fe3f93709932b5c95cec947316d8762f59784baa0039a33e8916e16ac727005ea0f1b6eec3601cad5b34bcd6e4c8f3b49fe0b98ae9e081e6d6aedc88dc3073e753a11d0c3a4b64fa0d4204446aeb877cad71f78b61442da7ac3fad1d8f581be0496ebeef0c4625c18f10427983675e57ab7a80e415217133352b5b3819c76d228f79047cea790440810040b878b2a54d18430c43c322f83150ed13ecf3349c158805ba0216b736554859f60d62c0ee8561597f52a51677beca0db358ce367da78bbfc6f1c3a9445c53fd91e0d698b26c7b8a2b4a201842f50e0d21e1539d90877fea7299fc08a831cfdecc45784febfbc462116a7bd12dcecf301a7da2a978f6527e57f1be5b52e833039d9bd00dcb87dcca99dc887ca0410646df7ab7671714e76fee5b78006ec1c7f53b7b5bacdfe0bbca426035067e7e00242a604c568707228ca6d5033c26a9b2dc6336124e329a98e78c1245ebc14efaa499183c7df43b916d47dafdf9126904c8b3559ade438b2062aafd600d3bfc3ee5f3123e50750faf9fe59571740d892371143706befe00ed39bcae1d7ae604a9bce4e889c4b0669e5fe1103ac5a4e615903a5c3d645144de577d4aa9d3a4e5abeebfdc96abfe5a07ff7d68aeab1b3e18c5a118d049e1e0213e2cf9da583d2b9f7108b972d467104599e557bb36a710d0beec84c13cecaaa0f511355ccd351da2192f450035d6df92b955b7e241755abe8ac2face7ca735bf4d034bcb289dd37e7336b382b0de8ab1a02b59ced9ac9f12a38be2a9d3215125ea5aca39b1b47db4756a402d2c5547819d0907cc3245a7ce5b3be4ae2ba86c62374337903c6d77986c496798789498b378227565d7b977b8eefe14351bfcf49d6eb15c3385e8f63cc9fd13eb69c37092781e8c2dc3845f744c1511c25a6ea363d7b3146b5602a07111980d9ab1ac4376d46fe5990e75bdce9de24b9af38bb6c65e6ddd410a1638b5eae14bc596110528a237a9fa7bf1838614e6e7f8ad3070a97cb010b2e30438a9bc1d0d1dfe9011517596cb1000000000000000000000000000000000000000005080d111d23", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 44, - "comment": "signature that takes 24 iteration(s)", - "msg": "2606000000000000000000000000000000000000000000000000000000000000", - "sig": "bd1c81add57c6fc6aeae596d5e88a9a40a1f146e21b923909e3c90f10a77c0451e9af75db5309434860e43f437f04063d72c40363967069240efeb1d04aede6738b9b9024b8186041cc5916b8cb0098fb0dde884e093911e4069949d720ca2e9ed86d442ff7e07f985348b569206c6640a9d14d3d89d6529aaf4b51295a6384b3a6e63a046d3e89bff5079d58728780fe8050369a06b397beefb82a6ae7d9f6b5219f993d34655b578454f62fcdb8421b8bdcbdeb43139e4302c44d1ae23334dfe8b51df8feebc24a936bee7b4b647826994da416318abed7004abd7f8b446a32e8229e60f1007b1fed5795a8df27392e7a3a1cf8aae5184065ca28312fc38395f70b9ea8b8cfcf1015b6dd4ea1b2c17b22af14234bf102a06ebb70a35ce2c9d0c8afdae728c169609f61aa09afb14ee9911cf41e6632a031c9342f8448f4f78ab81ea49cb57d18d07feb70d18c16479a03d4cf00b2e5e885113a16a50594901c6daf75f49ff990893370950684a8625ca8e882be5488cff442ba82d9b3b978e6908edaaab70ef89bafcb1327b3ed7277bda85f1b39b70d5f3571d5619ceeecacf60e29a37d9043a3cf41e03a79b4747025fe3ded7ede991939edc8d6e1491ba27e22a493ae6ebc189828ae00a13730dc5653da364a79f0d3fc00c0c5fcdfc7107f235b9781d5ca972eff4dcde7d38c1f30fcbd3e51d79c356dea6694d2ac49ac46850e06b509e51f6816e404b3de241cd3f869c68618709373d54eef4f244288e13a0fe8331a09df7073c9668ce07e83cea9a20ab76083835157e8c75408694a5a012df1b1e1d08343bd06d81f6dec60b2590ad6ce34bb66bdf6ebf0e21b1f2c4acdd25b7b212cde6b2bf826c13216f8f62be455202096de344759a1e66863da69cb0268ded55de9f41e4d75dbc15c43eb7aca6b7f8479da0f25d3116b1bf28ff205f8d25129a01f22ac3976c80eeddcad9e963fbd60743e8976e2175055bd6ae589c3808d41e51e2077d7e2f9a5fcf1ae687d7170b96bbf8d1cb67d146480dd38d6b52f877622f489354e587a4610756246d647eb1dd002253027032180490924c8ee0317bb4d8d7c1ef415a0df37bcbe1201b4d9dbcbfde250a8a89a7695c280a4be8361520869b5d23aeb6e7df2737eb1f28812f5ffb9b1302d5b030182a008ed813d8232347342abeb3ae7f7172d8e85947899714d9a4af587a43bc29fe14d577c37a2606178d342aacd2e9a33e159aac81f29e6500f7f8e1027d3c60c63498bd2e391e4be4caaa6c715c20316eccaeeb2b0f1e0b66809de88890a0d14d251570e409de7b84a4ef7d2e5b489a7ae7378123203ee261c06380b44cd6e256568c990d86f6cdfa444c333ec851932f27be415d6be7d8c1e063a44b62786fc1449815072c111f5b98e8c7d4d994c68cd21d0f07099c7eab7432b7853ba55ae27cbcd48be775b9b5a9d407c939206bedc59708f1efa733ce1b7f3df559b4df5b1bf8c27f8860bd837184cca59480fc7605b9faa4f1680c3389687030b68e343fc56fce77255267ae53357fbefe4f122ec52ae2caa58eeaaebab6cf7dbac4cfce5c95bc7dac91517a85b14c560eb604e5fecafa596fd3e76bcdb83da6b5f239ba8cce4a9e14957a71306e7efdc048b9d949a8cba9877ea329c39ba2034da897e57d4d8f94efd4328b38bd27052b224c7366085a578524b6f42ae9a2d047519e0575b3cf6b10a4578850cb5008446bb32996940d25c7da5300d9561ae96e43ca17614cdbee350e55e4a07be349d5b181ccb3c806a2cc7c1ac165a3dbecbc6656beae26bcd37be4480dd88bbeca8cb2c1d12d4594376d1876f928dfd25559ed402fab01b0a3a3d7eed61a845a31d3f2cb8204b7641d875304dd0b9a84957914fbb3a1d7c15553855f8122dbfa5275b0bcc66e49741bf4f88c37e830f4488b24459076039776f1342e1a5fc0af17d81d96c939e1159ebe04791fd920dfd6eb7d8a74fbda316d70b4d327a5411fbd0e25edf7f9448dc275773c2f05e9ec8f16006c4c8ce51c6c3b9be2f3a78ccf90468154914716162df15f008e64720218a59e69478163473af62c08780390b21638c7c86ff5ed90ba003e9511651601ac7ca5f505686b3101e53c736a213bb56d86438b9707187429d48e3dcece259b4f87eca78cc9720b1139bf27f5deeb6614002e5932d44f2220f22058e5644157e334ffc348d25a2be6859e88b27d365c5a07f86fc0d74b68ffcff73480a14973b701eda3a0d16fb39b86c7d344a51f10d3e4d80fa4a240d66621a436b01e549dca7d6ff595967a41ef9892ee3a316113f5df6379c529aacc5e332f4e108a613c799102f962a9156c2b7d807ec4de42b315a9131338f2aa35f889e385a79db045c042d6b4199ce0d924a859bf182f8897c1aff76c4470077c732147df78ad688c38f39c41c525feac6cc92cb0e58cfdbd24f14ce7d799ab19a57ce7542abe78372143b39b014678b7d02855d7682f2d1cbaa063a5911de020500d7bd4b3e45eca31d992881a3b9d8044d51c4ad2b3db4589c3c6aca5c714d31310e3ecf91950ff12306e52302b05aea52c2253a6caaa21f1c7b0b4be41fc00e4f2b318246785157f77ccdeb1f8e85aac7b97d28db41a6eb5524047565c9975b155d2aca2b98d85fc9d1a4e269adca169d145fa138899a975e13183720ab912051bc9523be26176b910d98fc8e191dbc564ccb1a0767acf1c5f9a92e501f8098199360674727968165293f778f8f87335f4b9fddabf278f65f205179a43cc8fb60047bbc4b26beadab79b35b1f316283b595046aee055d68e7e86b5664fc8b32343f9b488b31aa0649433248e531fe5d570a531613a50c73fa6bd546c861542ef16be17f35ec4fe92d60905b6baa3a0645ac3ee67bc6bd5361def91a6a9786afae9dd11c49928873b7d8efae32772ff1c5b2c065bd9ac18baf76606889dd80ccab7c9f0d3eb773fca1d561d5fd0811faf01dfb1f8c1c13010d23f8c1f467ed5c5577ab6002234c295c622044a306299855588fe45a48e00fb15b314d646d80daaa01d918c7a5cc1c3eed27f12350b58c6fd715fae1c932280dcd1affebe0d09335ba3992bd3d1db2a4b215b123da1a68c75de8e187297c625db9a9a1533a4bfb1ee3c6acb69f2d8149189d35ba80077aba0a1474d164ceddae3e8092c423099a0ce048420b03cadf05e897b8fece53857f0d2fa126b3b9bd80e31cadfc4400546eed633e1d5f0e4759b918eb675849f86931541678aef583b9b2894c905d7a5a0951355d5ce741c61c146f2324a372b87168ea7b380164a9e36bb3e63c3982eafd6f68e122a1263e745fd11dcc623d41c4a1f191cbeec16b2bd23ad9ef5a6067a1065f21a59bbf76a47f35a6ef3601dd6dffa00a96381d037e969ab938a57f21d38979c79480099f621cf8951094bcf4052d9c6b0c45cf35a987f254400b7d43f9ef50677192a9ea867046e5efcc8706aa599f82cf59ac0a67fbe162cdaf2c988addc0d7f934b850cf5739bf65b7053d280a79ec3e7e5bc738c33a883e31484d0003f2dde5fa7e36889f544d126e2e081bffcb41ebef6185e73399a9a336ed07c119cda65fc115290f149802f9fd73a6528d8bb05f0b210fba11ccdfc814d16cd6add066a8ab72471cedb354a4f60ca209153e7b0b1d065f37bc756ad1100ae851c1c998bd36c649f8c5a44ca5958dbffdd88bd925653081e2cffceba6cd4142a4bea47cc8fcca2f5e46534494689d45ff296dfe2b1985896bd71caaedbbb7ec7ceaf6d540c2cbb8c2c37489a5932263ba0597c3ba25a6ab50a5a09af3b9cc6a2a2d4411dd0d3608fd163355cbfec4a6dfc1bc4106b44196a4591af1b6e3a75e7b1f3769ee924984781197b9c2730e9bb1750005a65cc74689e8712c2eb16875c5da03a8bb29852e77c08a16bc23d777c99f628c688a023ab8431db5f3d0f463d90e698e3430bf2be8d02fdc41035b5047c1bfd21c936ae69af73eb258c3907efa308c71d3f8d9ab0d40d45c3888256d9c3a04f26c83eb63a77f290f2b58c6dd4bddc346266f97e55d0f044e7344c37652b8b0fa492dd5445e84988ffb92249fbc69be049c825186a2973631d5dc4d10896983bde511c87e2850318963cb1e239a7eba4c06b6a2e9ee2bebf127f54c487fa3b28636a2ebfa0ebe042adef1fa17913692ec0d1647cfcaf6c90df6f9b141d8fe9cdd8949d80bd9ebb0712bf8dc1466c94c625c9a9736fe4ddf78aa6574de6b1724a7dfc5bdabb99dc22cc3deb93d537dd5d1b75eeeb4505c8f6ec102ba1e694858ae94a66eccdb977432aa02f1b3616141c8c77fe5512ce888262cf2a3f248db8cf5130196f73dfb90dc716b0e21da55ecaae1abd53968a6262a1759724d2e4ace335aca4421b38ba903f501adde8bacfd7e6cb254e15a1aebf1ebbd812176beeaab97f205f570f5c2e96f9327af9c17514b2e62ab07161ba674e46c1dd6d77c070114a90eba94a212e4eb5e6fa62084418afbc0febd8224210444953603af26d21ad0a5ab8812044dc9522cd42605556c501aba406089bedd703ed61fd3df829ec92d5137c4161286ccc43728d99b2b5d2f014161e273238535661a0f1277177a5b2f86d71acb3cbe1eaee4b78d61a6cc400000000000000000000000000000000081319212427", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 45, - "comment": "signature that takes 25 iteration(s)", - "msg": "4301000000000000000000000000000000000000000000000000000000000000", - "sig": "5986c4549caa794e266a06862811cb2c44d93bb0ce32d7be8957b222eea8a487e8ea7ae835d09779ccfc38f48f7988f828b7b26db80d5e391c6e19ef4e190bec207775b5f0fa2d3872c8412a895d57c490c6da737df3c7f0bb2fd62a676f1a78389efbac474f277c4fa9b08f3dd0a82ed8876e3fd7a3b1614cbd5f0c51538621cf478c27ea39d6542bcb62338015a4098b7aeb69f0131cd15ad80e7e797bc327c8c20139992d49a66a63ab341a17c080db529df3c30aa8d76043cd781b3f6acfe97ec231db5f026a86d5a54bf0028a9c6b9452ee01dbf7ebbc910ea50f8e4480dd393466c8def5943ba822a67e7d5e20eb92243a84774e838924d7adf1e45c65cb85383c653c1864d51663621e3914b1985868f50c7fff42e04d57440d5aecfa221c477b7175ff182d461448e820dcf7b5f04c132a8194fcec3d4d02df24db406a8782aad71d7c27bf81e2cf4d11e23754c01b3dce63417e9d812fe5004c13c97ba3e4674b377c91e54c707f15f0ef9f131e8fc875d52b696fd46500088c3925da2ab487a6869cc8597ce2336f6e3ecc4fa42cce8c24f5783d52166046b19c661f3084601723196a65bcea4930a4814a99bf26c48f84bc810ab6829e82351641f21082b784b46e2115a08e32aaf4dbbdd6b9a5c72107f405c47d0cba1168f80e9842d4e47a0dfdd42e18d500e1bdd573fd4e4a7cc18f44953ea81d94bd1694bec08e67ae218074c1f179063587a65cffea71e385ffdee9a162fbb113d4247822e46f13ebb3462a394323684baf59bfa80cd0a1209759fd39f87a367c19995b92c7ef13216a39d0233ba66487c1ed46d5ffec611f427abda454f5be5e34465481898ecb4912c1a68067c4aaa33f525911d77e28e9d764bc1124a5b889fe928aa090f80e41807756541ecbeb620ab4d507ae30b17a684e2a18af0865f400904321a9f736fa476aa8c5f7edc4ce3d883c197fd38edc4ecfa26ddc86653f13fce2eba247df6cb818ece36df59ba220b7ae5cf6059eb23013a88ec4aad41d4264d2814921c9723fad5aa4393a646ebad0ea1dc277f6f131513bb77987c9275d9efee0f593f4126b490c1157c72d4de8676c748f8ed5b8778e5687e000569802c1273a52209d93b6de376621932e9743857017ef1af4f313a346c956b2a0169d4f3059a7ec5160f5485b8f00e67d04d36294e5f4514251c5001eb8da57398fd085d9564b959d4e2480b94b05bedd937a00fe713f1e894ed76ea0349b79ba0343db1761f23216ce929b20ff49cbb7cb2cf77d1ffd2675125e18270e081b18c86e811881695fc9df5f17842b1fae833dac14e1b10b32fa8e8d83789949aa0c23e46202453d6836511e4731dcfd1817aa02463ce1f175aa3c6955cdbe5c58d970dc0d58385bc27b2f33beb6eb638fc9d8fe285006436992d96948076b35a6dd50f97fddc72fe9342408841a5aab7893183d465694ce956fdea8f7539c4412d80f6726c2d726b23ee6efe01bd520ea514fb751aeac7767b42927ded102acb1cc985f6d371551306126678fd6cb64073683295cd6b84299c3ba36a7acc6810e4732389408919db59b2acf0f71178af017d114d9d543e72f74e0a6042155a34e9eb313106428d15f753f35547216e47500d3dab9877e0d8a8342606c4ab83e421c01389087f7763f7f5ff10c600c2308255701cfd04e63cfc435cd1bf1b24eb8bb8a6812d6b38b7fac21fb67b892e04bbecd2a8433c0d104e950771b2243595be35423833d46a6b28878cc16a033385e6bf6a94a4a6d1d5518d538fcb475af1d1c476401edd05dee0b014d5ce68d95a06c8a30c68d8d33419ab4843478708d938af757da39d45a7b77f79a8f8a2c944bc95779ab747d555094f1b04df45dfac56877377d5483b56ffb1ca69c4dfe07943b41a4d434a7ccfbcb64a374b61af0bb203800a10255b87c715a6366cb1b6b5582135e8703d64235cc714beecba43e4f31cc920c6bf59343d5e78e4235b9acfdd8ce49fb38ad74113a0feeb647f7179a33299b1a4bfa60af1e70ebb070dd07d33aa793e434c9d7aaae98f018e72b1ab8788644c4fef6b0028a39c30da55187e183413fc79ebe18a84561c15469e294900a74494e58339972508086dace548868594071467360f24efec75414ef502e5f389e4411150672b91f62984dda1b4760de4e738c23f95d9d6c56ebcb316e4ea71253368ac460e6a754faa69f2ece3a13c36dcbeaf142ba85cd506e30877baee307ffb945afdb387ed02399ff21aa9746d850c5637a937cbc6c3b03a27142b945c3da9839295a212d644833c0d85984cb5df2f7f139da90d66e6e73f51c9c3ec8ea590fefee063abf28bdcd2def788f25e40a7e25d01c11def224fb2a42b880f725e1cf2f8c08c8e6b3f80c90a6020ded9cffe0742f82d55040eabf0af6af911c336ad92f944480f46adbe8b5db18d6b34a3330bf2c50a2028f707d9bda1fad9ca620db5bf2037415e07d2d6b7c73bb0177f7a1bdfd349b87adbc736bfc7db2613eeaee51d08322f20a0e683af01aeb6c1d9dd9ccded7b9125b8458f052e7998ce4a62612b815f5fdcb8eff33a9c72d6e1b4fb35b01554d6bd287c43b8e4e8cc8465379b85f84176487fe89eb43b7c7042d7c9c1bc0f35c55236df89d0c186edd0cde61869489c0605946a936e90096e7f0614a74265adf8bbab764e968996ff759afb9603c359c195d7f725eb06701a49912401ad296d2240a6467a80a7fe2a440280eec32a300b2438b08f5152376c25550d0dd8e8237742af59c85020b4757afeb91aad5db9bdde9b7031445ef56956963cf27470cf5c914e267d29a70f7ad5b9c76d281e5a284db8a7d6a69b8bd626e47d6edbc7ca0bdb6df8192a230d8be6fb19193add1bd107d395dea7dad6f0901748a0d6ba6bdacfea046187f0b60a2f8b922059ae9565b6a20f99ad9b107c0a287e2d5c2358d7597ea4c029de58b4f13557df2012bd8f71a99d924947672866965ddd930abecfb5e5a4955f561ed9b7b00757fe8c3f219e7955d43f1676d544f678e3dd8f5ad9e36b3ff2b8ee15272924ac8255a53cb9a9e9202765746365181fe5ae49c96dd71f4c3967cc2a8bdb9a58f18ef1b8808e3ea44f076f4ad2dda7b2c78893960e844d3ff18aaf815286e5a5c04850848c3f25c0aa5f87fc0d62d286c0ce82f51c6e69ce0fabc3b862cefb8fa616cc46a1e34b3f893a4ae9b6d4de83c7419748c35df9841099ec8554aa5f7f310eddbde6cbbbf04f76336eb47fe161246ebab18bef7a9e3532c6a9ce0e2dc73579fd6cb1643f6f01c465ee4ba1d7256130b99e0e0f2a16d457d394d4e763ba36c918690ab354155d2fefda366cf756044942712cec0fb1d1941043dff020b16b39dfa77b064b9267de47f5d9fd5da780c173cbc729f17e44ec884a63b0eb3ac2208b725db57b6701391ee8d3bdc94f3a3664b5c6ecd2c166d037c0566473443345953646b9de89ced08dea5e800bc4aa1f8ad5f8aa6da89e9e93c2c31b1cb0ff0c9b7b4d5dc9259b65848949effdf6a1970326381c8ae4d039c372dc92baff73cdf14eeee4812524c85090cfe485ff6ac4e8bb5d96596adfa62138f27cca7befde57494c1166f002eb62d32b5705a7e9642ab4971bfa366f73dc268db53940ac5e1f34dc24b9a8996b527f15c69d9579b77b7b6663f2941f45448572aa5998b62c8f5d495176f6142c327217e1da4cff053c607673f14a912d9344bbf9ad5fa7e623ed769bbff53bf2b5a1c78f79e69fbf53fc99c6e171c90525803751b25ea6c9b7d496e8a7b294c3f2ff2455cd8715071238825ef6cf8684bf29bb490a1e3111fb305f3bc87357e7263e417cc7c10cb685077a1cf6f058b1108021f78a532d7c948a485ba35c50249c79add06a6cedb346792b4c02a480a2bc669954c24fb13fdf4cd6b5071b969677e5bef6e30b69e84b8a69c98de885d1d325526c58dfef5f72fccf7748ae8b024d915e14fa01c35e018b677a44babfd32b9555b749979e61bb4ef464f8010d1f8d457bd9ed6f956a6631ca7bc768b86be99fc5d2cff06d66013eb0b128f2245f6f284faed9b13a6c6e4a14c3e4a742967e598a06a119d84b5e3f8bcca18f28f64c9824967b6280cea61326ffa2b20790069e38265a337447eef2f739365559e96032d3e17349176963d9a05fcadeb86013c5869457a182f4a95f1bb5e4c64b640de8ddedaf516f7d80afc8a08d1bc5c50aed4e0fd32e2e3209958fd814abe06267b879035b05d251fab57c104b3fc4169d090b6830e2a64a221f67ecf08122f91d638d0a53bc211c654ef8162e625d75ed0a0764189312630ec3534d16a33d4e55f95fa5db64675b7ad8a06596faf5a8a47f8308b61cf16aefa2e6107cabd21524711ef971b77a1d4ba8ba1318d041aa7351324895ec6a45dcf5ecd14151d6b00ff611071cd686668ed28a0fb77f4dff6095aa72d7d99792aceedc33eedc40e30260fe127bceeab8a5c1e7edd27d0873fe1fa7017cbd9f3757fc5d92676d5f7e8ef5e85827be2ef8287d47403c68ef0c369ad5caed8bc88089f34f84e69f79309317eb49c2f34c74258c711181a425e93b5c5d7f308103a626d7cfa0f3d6b77a04bac00010819b2292e5f8794c500000000000000000000000000000000000000000a1116181d23", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 46, - "comment": "signature that takes 26 iteration(s)", - "msg": "4801000000000000000000000000000000000000000000000000000000000000", - "sig": "3a274d893c34e200720af504ad6cd4b00d7a534b6af57ba65951cfa7025ffa7004d07669533fa01ddffbdd752b84d2b44273aad42294a90bde3252f0c755fca0d12d203522874612dba90d195d5ec83c8bc6630671d7ca2a0ca83c89385937c5d4b1a1392df9a378ba3288427ee327b1643421695aded6f1ce3fb11ad9b4cfc5cd0720c9b012eda021df8039bd2b8d5f4f6f78b7995b0479e515faa6539e2f36646f35b9227fb42e23c6d49f3bf32c4f0d509b6064d5489faee9b5409ca29d73fb0eabc62e23b1dfe784940f7ff0a9560d4d7d278d41c22cdf07be384aad9232a17a59f401f3b768403f5adfa4a3f9b1085f09962f2a9f0e590a2432140fbdf3a416b45c8a5b206671e8121cbdbbd89bb35bc8f900775cc7f9c636883e9a3bd1c3367354138dd98913642b934e6189d1ac221cdd7030833c5da24c70de3ee205b88ee357132417e35509624afd510b73255266b23b735c9292540e4eaef743c6f30d8844b044b527333d2cdf16b37d1f1b81637727b1e7376ddf58287d01da6d000371428cdf431995a7bd02ebd9d59f7d2a1cd33bc33026446f4a02132dcfe734d5f8f993946ea932f1a4648df1fe0d76db2f613b269d908ca87a12a3948d110b6bb2048a1780c8bbf6cc5d5385df362fba179ae42a10ff706a106722b41bc17c56d6eb10130d31b5bcb715fd6ddd7aacb536365c5f5c8b92f29f8f5d65c0c68f382a7df50111707628cae2ccf7913174ef53dec3d6ac7111c1bc40264d8e367c4f42ed57cffd874cd7a5c698fa405ae3121050e302da8ac890ff3aeaf5e388e95023d082e7ec4ce625fa3340c9410499c9e1709cb4058edb31ca1f723626290c8912897f73f8a475a3f06173202c154e33812135ac26adcaa585c72667e3c6f20ceb1ef978815d4907298d1821c7a5fd76489ad83c118b38a9cd9dba5989c5ea00623c964dbaf4b6f072b478fe1b13b8f1ebf4b938ea8b4bcfb868e8aa43211e73439ca50e06d3f5b2d9a2a638ac113ace0d1cfad0cdaea234921cb447be52427c9726f581af29c2046e9a4e60905910de2194a624df7f4285ef058b430d9803bcfa83be0b75836f317eb6ccb2bf32594a3ee2765390aed29070249d1a899fc5836187eb65685867efcd75e84948769d9794686afa30ca9500a636a9a90f12e2e09f2bb5b716a5d970efba2dd317f9e0d5819db99f0d041ccef8f5df8490ec13854eaed2f86232c10dd9b0914814bf4b68679d11d2feca8ad67a3863b73928ca8fc2e4c00adc5ab81ad699c12a592566e3e13b5f814e43be38e32d6973f68e7e5d0cc7479fa5e937c889da2de8763c1abf517aa5fe879159328477617980aca382dbe22831a8ef278591aa3e9e9e87beca16b873724d500b03cdf46eb3be3ade2a3698c1189d376fd79b62f3f491cbc925d04567b735d43f8f622e2e7520ca8b9345bb4e5163be6ccd63d01553a148581e1088eb666bedb6cb0d3cf65abe30100bc530fd1ab6aa111f3780aae419e564c64ce6253741fd9800b84add684500d3ca1becb03832b3471448c1bc0251a7e1ecc84928983863bd2e6ae09a5840e9b9cd74ce6b40e78cd5dfab8755bf36b6146732b599836fc2db9af2688cca570c70dd7c7fd4041b9a4c8ff98c7981b1d09dbd009243459864ff562abc1512f2f844713e3bf883b2710c3595e570bf77d180dc47df51d79d505ec4a9895059d5d3702a93f5433985e1b51078199743508a398b2ff73269d3a566b2dc64cd1421c5a7198d544079ab4906cb35c596739e5d7e1f9c212db2278a1dfd2d1c9628f5b59cecf15b6145779e9de4ce43bcb5cf880355365e192852fcc0c85d39db6c5052633428019a50ef7266ab9793f9e800f1455f1fd77e2f90fb13e84af7ca933a65a07740d6d11506f650755dd8bff8d34bcaca2c2764b23d749c116fb2f2688e5abce0ea28f79c6ee013b904b28698a17c8d012e821504963bbb6af7567b12bad96ecc3df7a69d22cfba305291e7b7bb6466bf179a77b8d2481917eb491ceef67cf84cd63b5bc87b26441108b03c8126813a4f545e23cfc0f285152cd5f2f77b93a000008c2ea142681ab1b9f7b076e61cae8e93bf7759a7f2bda2cfa86b9eba74b77b03b53f13f6fdd96681337616628e06a2bcddc4b4fa4ae12c0171063229f1eeea4f28e2fc26a43bcc7318edc608c99b898212c3b04bf85b33abca45749b87a76e2240b987a63a29d29f01c78fd91f3240d915adf41f2b5d80a848781dc060d0ffa737a0c6cfe5b453cdcb2a50a39d7ccd58565a3b6bdb2823cf9d7ec1a204546eea31a9db531b51214547d66e85e590a663f391b0bfd0c67a2271fa5fa6d419c659b76a7254468e80e78434b786b385c91c6f9fbdfae0b1155b87a708e922a0c82f1f0189e9d953deefce4f139cf6d0a8bfe67cb5f6cd44627750c79f54cd0e1272843b5d08dc1e192686ced88eb3617ade45516159b39c6aa65d197dd4758e3b290c17b9112c04c368ba01dced699d28de4d89395a49ee36e931cd3591d3db6f26fe300309ff6cc1d98e0d7f03f30a3b6b8832b77f31f951d89757f1d789b47a87715718f97089df9540beac7d7b05776e30451944bbe9de43bc7ec69ec984301a251e9adde7e83d5c9df050d063728c6f6bc2c76e8906eaa87ef040729cb00aed35830645c81d1a39a1e77bafa6d4f06b415e586c42b5aea4d8e6c6a2061ba0497f7c93a1df188b2d79abe9b7373d6f0f63bdef5edfe82b37a690fd51f0b044cd3192455979a768450f7679e86ea1756434fbe3fb8003f376d28e666fd4728378b316944cc7899b07a01449d53314532ca8fe04007f2c37a5807a53468a433d62aeb4c138ce3f9f33d3ed548e408e7ae0da25b5180a6773f0037422d7eeeb0b449733be27a6ea43f26d101b74fe47be2babbb8925df95e6de1498069be6d067f232443e11daf9b8ad0566c923f444fc7c6705a3fd8b77fbb2ab13b9a7492297d6a2274e4a3ba46efa965094dd4005b0d9a32510a6ac9c172f705c26dc81b702d47166bb8a930f16f19419dcba6ae187ef91d79fad465485aecf38a801b8866e51ea5ff1d93991c556de9d91867052b03ca4ae4552e6f0873f095209bf8bbcbc64dc90159b105be69d436b7095fea150d7fdeba96746178e6052105b11abe7795504b078eb8a647af1f5ad3d2186282ed2ae7886c40955b93448036412ca7dc49f2e562c5afe8694525711e7f6e49b2515e5a87c480479f514f4bae5119ac3dbcd730ab3c3f2f06d3fd81a0475bb1eafe456dbaea87d2cd880c96d34c348e4650cda3329f6a082cf8db220876cbc410d0afc945b0c059a3cdd28e094fb7de858a3aa75fe3f344fb018a121b26d14b970167ddeb9d1eb3ee53e32f14611c05d6641beaef94921315ca760135961f182d1747ab5f66933945e1147ba4e2dddce4bc0329f22ac00ada5d4d311125831a98561d21331e578ed42d0b894597be1172e7261decbe9ffe0a4420e2a031ad2143524c3ff272eff4646acc7eb60048e99c733c0bb7a0fc957995c8e6656183f0e0e1ae552dcd5fa7c8df4c9ec37180a6f4cac16366639fbe2395257629aba0715ac791be689d8560779014b8348d271aaa91073e5f1fd2bb0be908bb68991dd59443d23dec0dfab6e0b7cc659bc73dcab4f708c48aa53b8433e787f80cc8803eb18d6647fa629dee201e64e04be60d32f5dccaace5e1e2fe6742aa695c06d9839eb30121cf5f145bed70e3f191f26abcee01a6d3de849634a4466bdc57dac8e766b9fa66c57b8412df00d34f586fa9c3322a8847bbc0cdcdbc6eba26a3d88589474bd928aca477fb6a766fe375e224ee54d17297146593adb3677c7713342f05059c53154b67f97a4cb949f5911ea2dbe43adbccfd151ce69061693d51aa86f651d981f8a1221b8faf9fbb9dd923ab5fcb7ccc625a2984d59a644c50cfaebecfe76193f69b4e1b410a607418cf09e268fc4529cc8b809bddf0c594f25248d09cc3547aa87d08b330d4f783bdb17e238a17a481fcc1e1a38676ed2c8849ec96226bc24e085b66fcd15fe0b5923690e80a4cd198ac10c8c07af0688d77ce0125916fec05aacf2e792c73fd887ce36b007a650d4033cd1e3ddc5c74c2f9b68502c307790184ad1b7dd2ae3009b155f95253a480f832435e8472289ea454d3762c6551b07335137872c2feb4b824211b60cdbd077783fa8ee0eb49d506a37d77c4606c42d27d6c477d20d4ed89249ad3455d4fdf53fd4122a82e5114cf246dbff360e4427704a7569c26bb477c82731ed984a52e3368f7aab7df25a32c1932f4981a27d4e82e0b61830b238e97e7e601abed437de4a9a009148e865cfbc75a96b14315b1accfd252e1d661cab2818008e1841a5773fbca270756ccd2166318c553aacf82af9504134de4f3cde8992c14c0fada09364993e7de7fe42f8b54996ecff54e722b25fd51df037d4d3493ded04f6507c1aff93016a49e1e0a6e0da42cb4630a79c5aeaa61ee291ecdba09e1fe36a4039fa456781dafa4defa0ec2bb0b195cc0fbff9054fe4442404d111a7a8fe75f61523dc720347fa80816d1280a03c9415234996d4f41267688892b5031a1e344ad3245086bacbdadcf007185c6d95d9dddf94b900000000000000000000000000000000000000060c121a2224", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 47, - "comment": "signature that takes 27 iteration(s)", - "msg": "c302000000000000000000000000000000000000000000000000000000000000", - "sig": "2281ce37d3d0d0894dde142b097455d69e4ac08e358f921dd86fe71a294db8b2732912b1de60cecefc89483393815556dcccdb912938f8469aaa536861d8c3d315b8efa1204e9c7022dc44490ae1fd7e2e9d640b6d0ae8a3a3c01d6a5d0594a52229c8a7028c763f688d3f72e3af83d25a01cfd3b6a7fc31e34dfbba78ff78effec007555ebf96b4d9b14eefd1bd19c66360bcb1e5a77092f36e2d749eece8c89050003630fd0c558bcdea939a53e61ce80ee98842cdd8afbd8840356817731fef575cae80b3eb8678d9884ecc66846c625d1f2d617d51f1fc77fe8bffd994a483689f9f5f05132706308448a3342718d487604e5006d46058fd1fe9302410171f93c3293737e8db35aa27bc901cca074ce2e19c4dce9d029c36553cf92a1500612b7badea5cc4e20389eb01b854dd547850976df5e6d9f74a30c7ed51b2debf80e9e379cf2645d6afce7757c449ed673e12780e2cbec4aaf1732e093b255ebf8103bd41be041df5f0a18f13c8f14097e8f998dffeb55269d2c7f882588e942eba0da32a3a5a193f7d18921ea5c82d7751dd939a448c891fe500efa06632faa47309a8734fa2f700659b9db7037320c7c00ac9b68f1f7de71457289e9b8290d6a203c48c21437aef6adde8ab2cc43170e65f1704aff58af037d422d1519bb756beb6f3f4c0ec653865a354658f305a495d34f183b5e17bac2ad98bf5246b440dc86758aa047f02aed76fa5f27935b3bff953871cd3de843688b13514aedee789bc8ed44eacc66d5b8d6afb80890fbef7c6bd87efe597868eeff71b92820f353ef580ab5e57faf63a762581ef91f864c99dc34d7c2c8dce0ec103a61a443e0c6d78cb03788974ba6a2a261b31ba71f3db05c2c39fc8634fdcae6498c46fa37bca4072e1a0b2c67c01a30b89b944e6a7d2298504b1adf2a5cf00d02efb14b2dbdd1839c935a3620e1ab8dc1c2be6fd05a79af94943ef98b64a8c86e47e3903dc84b7ae6e84caa9b79f2996a015ce6a4e3d7274d43fa71526fdc4d9d9d364d05a2f7f732cbffc9f80a4e5268f9eb57206d380cdaf39b2d64a54295dd31a11ef2f2f4828f57ba6af8ab69271060e25a1d987231d6692bcd82247727a211804879219cc981c1ff6cde51bc630b698e767107fdea768ccd0efa2c1e307bcc32a6ae0483f94a0cabe09e01e2edcfd08445870150f2980d23bad7b5187b0a3eef6e6be018a09b67a1cea314e588c0c41ceaf53206859f1712bde6f2e8e7d30209225de2de928e4d42c34344388feea70b1da1da7b0951e0ca7acb239cf95510dbe0c3ac01187661f2ee604f86db26abaf8113358ec1fa976bfdc0917a28837f63a1d87b95bbffd2266fbd2c50cb6b568782049627731865c43d9a5b6f637927044a49bd7c99efebcc7a65e773aa8e846f4c793d4e9c193ecad8701e6cccb7045b81b3788f23b1b523286f2e6e4c570f2b6c99bbf14d5a79a0faa9ee55c60c4e23e06e8eefef6706babc9a2d0dd3b81c2c8056227d798c8a55de8a49af91f9bfcdeb8683a31e576ced44da0efe91d20f4d15b1c14cf148914b6ea366f676a97f60680e3fbecb29e34573da9d100aa525760eefbc96f9864ab360623ec1f41ac55750af455c0f24d463c2f8b249d49ee2fdaaa7f5c54c9650cf1e94de0e56f04ed2e1b0a02488a3d608f31e67919481d53ceacef129e92b3dd56b199ce2b7df00abc793d2ee82694490ed97df05365c6205e3c502ed9b8f712a9862eea823514fdf9d7b2fe4bdb9754f1675c5b453a4c2ca893d584a014615309d346823169f732fb4ca1c1cd84ac527ac560c9fef1a207c9f35a9f898a06601a5b910971a3319f6c29d0b39df7ffe09ef464a9dd924b86b641a0b66432aa964c94b608c8681667df08027ade6b013173956a73a6787c95a13fc753a7d4b2fc91206c864be82382cc1a1d4e4c87e0d1d9a113bbc39f377d3de28f63df010df89af0cc3ecf30546f2435adf22fa43166dc24f01f441d7d97c235c5dece7108e3601f878b1c46c2ffe75363bebcd293caef5c4b0eb88d88c1f340dc8ca4cbe5552d9136ca1e3d5d809cdec4c4150b86e75f02d0189565ed27b41efb8ba982256bb38ddd04e61b3b77405fc5e5cad0b0ad58a009b68cd7014fa45ce704b3fb295d2f52953871a6ee94fefa1967030f2ee1d031f826ea9102d1701136aa5c81641e2a6afef50624785c8c2467e76f0f903be8bbe2656fb92691cde368c3f9a6fa870f50d977b8b5592922a49c0ae14d82fea5af9b2f7176898869feecdc76b6efb0472a0c24c0e9a2a2970d74d8f9dd1568ddb1a9c7a835e33332236e5065d72bf4522d4b18c7b3d14295a5986928d7f74ca8b63dd79f6fd464c5e0cbd98ccddb1318eb9738f32ed2f1c3b4e929e145accf8502b8a4f3b8f20afec1fe4cef9438ddcfa55a505dbccac90914531f82d2aff47976b8ee1e20f127478447896b3fd2c1a35be09ca69ee75f9958e569b3f4951149d32de2918fbbd3d2b5896f50961d35fddf0517f597c8273fde3712c6127d35d640ea580802ab2b5709399df4ba0e2f2a5a06013dc6779373672febf0381a25cd2924ebb597b03a1fa0f22ac14d77a524c7ab5fea1ccfdc1d55f37252121dbb050555508f9d9fdf0ec12153a48b12f67b6c95ad844a199a623dbae872bd052ab47289a3b6ee103aaed7755accf08a38618ef4d4669ca931d0e14bb8e9ce77e54cb61ed64aba5300105a85cd303bcfeaf167663aceb81eba106ea896094060945906bf4dbe038826e1ad58d1ed44796fcc7a464faddf16a588626f658fe21a526988e78eb129dd0bb4b645b2cf85af83722b4385f535155a1a61af0e6cd5d009f37621b3393b67fd29a171204848cd66797dbd3e43c088c473c26f124f7359e09c75e55bac5b43a19542309acc4b0ccf961cec404635799ca8516b11c5ff7a6348dbf0742a1267abcc48235bb95835047c74cdb1d378351f283e07f48945c7807fb7820564ac2c207f3ecc66ba24188dfb22801dda9b75b308593ab2f96e86c4af563a2c355f7e153901529e580edd95b7ac8ab3e1211519f99a91dbec7873b23b18e776a2904af31fff2e8e100b13e777e5b17f8b35903f9c9558499a1f96a8b8c9f1ac5cfa676a194d86ccbf94eb02368b781c301ad6560210bb28b5173da3a447e8a850279e0b65c828dce1c8e7712973f8a08c4159a9e15364be3d2147896b1a1ae214826df8643b4e573f2af8e6302c2551989ec1c8943be72abd2be35c4ee70fcb99baba7ed4ba46016f24d490acd4bc987c2c434b1dbd8b39ad1dd2004fc7a174ea59fa2f2db6bccbfde2d208e6964b128773eb6eb6d1045df96035c250d56381d451c52503b1f66934d87d449179979e4dd50c6274c1bbfac72161627b288029c5eb70997caf11ad6fc3d46814b08aebe28f40dfb9cc85f4056821d9e159ec9c4dcb586fd8c0d8881566669a8a961e7b40e4b83d068fb80c270f42dcbca2df7bd6ce6890e9024de7bde7603432253c14a0d057ad528ca4f548012dafed4b3174d851e4d2e5c6c168c2417003755bc5a8a445f3d38659c715ab6ab977f1cd13fc9c6f39dd2070b1cee3124ffbfcdb98205a1a2b88ae3fb9f245579bcde9143960f0b897a478bdac9a481f1c53c678c64a84b0fa3240177894de0c4ccbc089f14bee70f762e2480ea9438cea2788e134f0ab1080e34f22a4fb2ddc9e7da057bf0c5614a175022f06b5d126938d97d98fec87c0a917e455b78f314ee56de3251692cc3c2d9b243aa149171a62bc7035e90044dfa0a190773fbd4b00fa7e24447dd5d5722369a74326f29d48c589a4f16c92dec9da8586b1d4af66c4bc0da57e2aae07d00f9c35f031be8256b2beda0bbf06fb22f3da317b4cf22d81e88c050de9a31de6da3ddac483c49c8bca2fe25b6eb87649e107dab2c9b061885ab2a4e62debaf453b683665e7c2e8f3fd5d22b1d4b780cdff2a26b31792f646968e726b9f4708418a60f3f57f9551b9cc7cc68bec0866a294edb9978375241345cbb6bf577268a906002f9600b7e845d36ffae2c7de9d018939006302edad2fa860a4f25cb4a90308d57572284f97a7050b8750b2e02c2f8a9ad5377909ad117082570c9a5da5f512503d78c60621d41964bd12f86c89ed9c74f586b50dacdc4e52b039ed6be06c568782d9049bbe992cc867894dda3f3cb593ee9fa376a3121005b562ce8c7940d4d48960bbd95f77299636e4f1bfa4ac40bab82bc4971778faa924b6039008169efaeeb1ce29d9e44813f22d44b18485ee0a216382d0c83b1b59e34b2dceb294f9ca6cc848e018c89291525be0920f827033b5d9857c3b12b6c6e65627c132c1dc2a5da893860f5ccdf9aa2dc2ce09c45d7d1d4ed55c130bf5400ab60683ed1de5db819d42a199788dadc80e328324f6852c6021eaebbda57e276650c4d06ab792ace94f5cb32b92c40ff5403efed4b94e008ba6dae1141ad079791a3570bfc4f6770fab3fa3d04836ff06ff4ca8127c68090c36810610d960d356568cec1e66ffedc01eaf875a49baa5e5be0ec01ef1849704cb09877a2a80c100ebe7a790545e268af2f1d70b1c22375996aeb4b6b9bc325e6f7ff5ff4d6166758b8f9a6378afe0ffd8063e3f505ab7edee00000000000000000000000000000000000b11181d1e26", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 48, - "comment": "signature that takes 28 iteration(s)", - "msg": "8f07000000000000000000000000000000000000000000000000000000000000", - "sig": "17d5c276a96ec04caa598377bb8110226ddf85feb0dac0f0d3a4bd5ca33fb40d8cd5d752d889fefa66c900bf6e909ac906516c9e813875e758663c7fd2636ad3fc89ccb7757c0eb799010367afa46a17e113b16d546a8f8ecbae132efc625e3bc6054e3c900a174b6d47b3965b3178d3b72b0472f37d172ad579de128e19575fafe7ea64ea116b63fbfb4d5b5fc956bfcb6928b8db0cc7c5a889285237fa7057b3423cc7f7b950f834f7e4a7b168ad00e841ee13d382462df9d5fdde517e759d16e48963f60f117502b74e97f680bcb4ae2c35af009d9bbdacb794edb131715470153a0eead1cfeac73f8c8cd157cccbb17cd1386f65c4fe09097567794e2d7e7eb3c358bd8b2375f8f9d0f32d28bf863599939ff8fab29401d6acadb1b90f2bf1d9bc26221c67e78472c7ca78efb2b4ea49dee8489c01abe9ee962277c34805c024de06414c4ed63370ec5090752a6fd19cc36a50d3f714ad58ee060bf67b6f4f988c35d5cb1155f702311eadc7fe25ec25adf929033679f5d0058a45dcb58e8b4079b374226e26003e5bc5f76eeea6fef86af3ae91f33c8c359e2a297a69a105817c7e67a6a00a4d8aa31fc848d8c4f274b3b5ea34a2817b515a2050ce80bcb0c21bdb81f0515ee05633d94feea1de19534ef33da85e5af0d4fb0e81e4088a981392f96f70dcfdf0d0b9d308c26120e8342f8b6107cd0bf3553554e4deff879ce152425e4eee9860025dc4ba9bb090971903a0db863c043dca4e8fe35e9a6b0bc26129e18b94935fe816fffca11357af56ac6c837f0af36da11e4b43f74a0ff2ed62f18fd5c02c7a064e649031c2d8f22d6dc1a1b94f39d3065447abfd9714462e137bb92b720091477ee1c1c1666f4b92d6a8b61c70d49200c86e8cd9de65b209a262cd0c6e6774810daa62b16054d6e18955e4a92d3015ffffc7584bd5829c040ace9011d5056bc914960ed785b2225aba0eb56346aec0d7bdb1a3c73d1e39c2a395fc874cc56648951a98549a04eb71d30e38a90d7e545fe92c82a7663b10f761eaa01e96edcb799fda895f9fe14c3d0ae4922f34a89908cbe60c107bf9d8055e050d08cdeaefdeca1688a7b26e2ba558650e90b24306e575d046e1f3ee2d9c3cf159bb20d711d26c92c11735a50f40184c97a2dacd02a1acc4abe4ca286e4c599b4d4b5674eac6cdd4e472559d59a13dde5d4feef9bc47d76875790c8036dc29448516be1cd56504e97acbee7cdc5273ed3700aa7f459e1c25efdec86402f181664e764866d8eba3adf852b83cf135ded54d0eca77527870650da0f2851bb4906320808d302feb7e0f9db7b8cac98a62a0cc7cb97e7f8a7ffbfc38a477a201719d70172e59e8ea89c482e61633f9a0a3cf672f6217479958aebeee3e6f06ee8ab9f5e9d0523272c5164f1f94a3711b3e681ed03c177a692819ee56da4059ceb171af119c3976b197f005fe8622e1b4415f358fb34a73215bfbaa53886ad84ff57ccf42b7d57847a26234235ba0b722b89f9963446d67dc719bf8de49f4dedd4c516dbc1e1d74bfdedd36479694a9acee7dcaa7df55f978d38da1d183bc9c0cfb049c9f7da0821be315b6118d3387734922723ba4919fb703cc2446bd4cf30c1825a8bbe7daf08219ac5c1a3f897cfd7f66e77de3d0a0b7b73f1166d770b9f7c0c6d41320994aeb526b6ddd4afa6dd10295dbbc5082dcd35e43ba91dc972f78665043228a14d75cb666e503158bfd4c668a29d358a5b2e03fa1cf5bf15aff4890813e52a2358ac79174273074c118b63cbd1ed85c8c3e9cc7ff5c1c9bc92b848bde3a7bbb74447d430490b6bcb86158120479a02b7ac3ca61a07d76dce2942b1fc09bb33972695c0172a66dd4fbabe80e333dca17aa5806eaad072f4b17300135ac118f943dbe9041d4701b424d1f88b27b8eec8308a5bd153f7949137deee238c833c57bfc12b87bbafac73e1505d0e92e873d53772f29c7c3a2e6ba4e11f825d631a9d1caa3e3f8985ced7f49235bb907c2074fc368b77bc90b6d1e4cb987088518e054f767127361d2faf1d5feb35cf9210a92a4e3ef144bcd45dff7e2c2757d472d1255549db29fdba7616f9f9c0c472c0f4349588f94e77f8f0cab52a50029b93c3f08473f512a27c319d45e9d6b52cfada0adf2dbba6db96b326c3594f16880913cc6c1b3be8f4953d95ae5096f03a4a1224135e2bfd4b5b429fe564405dbc2ddf004f36bf633e977887915a44105ad2652fc17c398fa2e7c0eba0f69fd98baccd64875dbd5f2fc660af49a5b50dc831f41890872722d7cdb906879e03ebcdd321a0e81478276733bc121016df6c9a3d1a574a9dcf6ca489f4c82058ed0002c367c92cf87712348b7c774baacf10c778db313dc5c83b3e0120ee369780827532a52431faf43b03585dccfe97ab204c33fb2b98c9531c95f6be5ec435b0a8aebd7ff4310bfa221be76283e7534679917199f616e0e05a49b382cd26a4baf0cb0e1053fc24bba4dfd2636680f750c9c69fb34481ba0f62d106937ae7959604ad554fb2ffe53fdb926ef5a589cc21e5adaaa7ceff3e2a8ea8606eeaa79a05c6d9fe2cc674eeeae2a13cc716720472b0459e8fba3f0d77d60ff3e48f08479deaa1c098547da855b59fa12338baab82ea960184b72da4adeda15666610164743db8701f2b6da9dedeb2a147cd1e4fa5125e8f72ef40f14c88f73fffedfb6ee327c8e20708dbc0e4eb8b7c969b11ef8ed3b63c55027773b228f08c3dcd2a24feb716bcef64b5d2d34302ad721f6cc236c6694756990addcbc0d6d35a6e9a9445de640ce02ce9f2b081f09774ae09fda994fdea5c63b7aaa37db7268c56e11898856e94768e47c18272285050a1c182979a63a573c17b747c5393b8ab21dd17849a00889c11bfe28c60d1d604fd716202949adf2bf49db903841f4ab64bbd7af3de775f66f219e40a6a61f5c2eef5377a196ad8c7837b4211b531aed7c9969125994d6ede189f872f24dde4b92eb13f027646ede13d35d02c58f5cc094ba76873c817367805e2169011760e22b8dcaa5755180cd99c7e8318ff61bcb7efd3ce0303ba669419937e0e41bb4bfa960d773a5b73282919dc9d70b3427942078e7bf1706a67ba52f047c8795437d28bdef9e78e95b3ed9545177db31920d138454238759cd45e7cdb9c4d6bbab70654e2a65e1056c2ed98d9c601e13a356ffd254231c867b81b0f9ade2affe15ee88744629eb79a5cdc5ee4e485d663bc72cc1faaa61c651cdd2e9632019a747d1b342b1f493a1395b82854f888393f4f75907b2af70defc62e5087f1f4899d30f4a97581f009caf78a29b20cf38eddc1cd80066b1727880bc936be866ee4a14c994790cffdc7dfd977d9af1c3dd23d5371b8dc6c2a3b043e8f92ac954e7839e1b1934ab04b5f51e8c650bdb4357c2309b657ab2b968430b903c363532c8ce386ea00ea8f8cf9614884ad42098a01a4c054853149a5013664f5bc69c3bf9c237eafb9e97629af355855936f56d0d943333dbfd401a89a8d3b0f6ee8a5c7916d887c73088c481ed8963c54517040846fbba24191a1ed20c09f2cb2a0032e1a68e4a922c2e1bfa51ab6e7326490953b7a5a1197597c7adbeed7b43d6329c9969bad56140b6fe5819e5915ebed1ebe120970639467ccb2c7dc5c290ad0693aeb6ba1a27a416b3e21801ee1f239cf179a9258e9c527b5e52103e7ed22f67789a030530a536d90cd8b6e08f389921779ab97fdb4129d07a3792e4e1a64528131c38463e6d576d554f87207406e1587d6cd30caa6a0de6a7f0254e334054cb9f39430ae1b2faf0641908c09f3ec50ed1ca74f3655457c96b1e29287ee075c219c82c9fd2ecfa53117c97fb46f8398dfd351cf035da70345999dd6b0ce4569ad448f6475f343433848e8bf886b45cf4166b63e1347a60a66e05d76b6489c4c1eb621e50ca52f1cc75a9f9304b6d546240b28c986883e2a0be4113f8d615b522ccc40569978572264d277636e82428af59ceb8c2b175b4d3dfb053cda248ee5ab5e44b51d6865271c9aeee589e2b2b68e16f91be8dea83a5144b24f5b410e48877ac7f1a734b45c5934589d2f5d5acab37638fe9a5c52004958be19b731c5d98a3339df150a80e2c6ae6ab1e6669065e9eab2d2b1b4e29edaa919ed1b1462f02b7da4e651fca499f6c114434e1775afd9d1c44c55ddfd5f7936687a8cd6fd2ae67daf6160749d146c5fd1eb7d73f9cbe8ba3d4f50f98da9e221d2d5284c8c258d12966f6faa422c3872021d71018839557d80c7d7bad4929af61bc195b34800c7a3a18a9935cbe648a383f4872e796b87b462fd585d14e8ff432777c798a431b56714e5ea4a44b1f049435d2e80e2d7e378c97f8c289449919eec2cc8f535fccd6f53379acd16b55db0bf7f4f42ddd3228430c3aa89d632e9fd76a9d71512537b3984f56b11618fbee1a79a5aec4256c4bd2d7b0fdbeba2263934dcb4319c850776fcbb0b9e1ddd9da387241b0d7a54eb16147d0be86ac55c35a5a2222827339f73ead716ade758ff346d3f981fc5e90bf2aae42cfdd059ee634467d09214239119ab494c0db85111333507996c4cee61423264662b6e2195a666f71c62d8c9b9fc7ecf6020858eb4998b3c2f000000000000000000000000000000000000910161d2126", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 49, - "comment": "signature that takes 29 iteration(s)", - "msg": "2001000000000000000000000000000000000000000000000000000000000000", - "sig": "d3ecc39ab0177953c2e5afefd2a75e55e7795e49c87a44706b7b4964bb9f9255f4b24b92e7401e86f5b79be5dfe9280112599526d7421d52c9d9d49626042b94ee4f2ad3295f4767936029b153c5859ad6c119b9f35504ec3fd0e002cdd67764aadec5e38b11d79d458cd290ede3372a41c7434f285fc4ee45599c02c85fa99b5e0b96fca57f07a494c621530be5ed69598c2adf48230caa2129c470052c9047ea0a622b15efa8c9cc5b1e8c6970b99fdd7281273dba1399a319428f79969fc0cf07785f22c6eda6e768ac8230e440c8bb05606a9cabebfd264d1316ffeb9d9574103a70ab3cae8f22e04c3bf97b5bd293ac496eebf9787269e430f4be6a7591ae1fae037f76b14af90046e6ee0edbd2314fa16ac3eb69d69d803492cb5769ec93fc197d2302fdd46391a724dd51c59229246deab0809ba4f1999c0fa2c85e462c4c26138a4a9f299bb25eca43657a7afe4a1e420faf756e3bfb77900da25bcc183bbef7413ead287cc539f03de4f56c2ffbef8312b5909b87977f16dc0e65245d4d1069e46bb7614034ad73acfcafd64226b692dcc03e695bbc78ece5b1a5926a346fe5e8aeb81a3841cfbe010c69c9b06a0b5b81f772f8ee7248572279d37e325e17e81ae2479de6702df4d4c376be417c859921c7bef00f9b22bf1c3f56c36ff9475eff8462102f79c75478697838b384b1c57f842780a9be46d3c4e6f7c38da187945d283049d8c0278f3237660e612f50eb73b389580f740f05382a732b94bc7f3189d6cfd2de2c6fdc6d7d57de3b897df45c44ec7ecf1d4cec370d87f4cde4ff470ec42df2ae0db86f172b146bfcc00b34d4672cd80b06e74c5b302a7e5fa7996d930cf821a22432f40ca9ee7f3b0799c87ee1c20ffee186c15e73d32fc4a3d77853b0c3caf44757369fb5956158315358269b3c93db934ad24e0bee4b323359e97ba982d78873189243a0eb5d7760fd842fa2c04d52f3ea45f99eff1c236d833bbc8ecd88604b7e33f8981fdcf2695069f10d8de32fedb94f58fb438dc9af842698d4651c74383b63e2d8925211e02601b8642d34090449ec8703040ad0e5dcbbdd46db0f9e2f29f590b6688070cb2c868d41d3ec67d7305ae6a0e39d9383df31e30aa8071e481c1133c8420b3e5a3d7a2681f490039717ecf088b219258c4449ac8fed4c40c805ff4b77d7c28d0b5a0c8cd2d19e2370142a4fda7eb0dfc9a84cee9e4c845e8643c8108cce254b716dc4b562fd2535712ff840415212bed1fd2417279ad11b743fe2895598dfa938656b7408e5b1497fafc13fd12b3fade0d40a0820f81c430cc50ad677bebbcdd74ce14682944b9e9024d681759b4793c246ccb7ca40d889015f752f73f66e60c61f5e0f459bacfc2c413b0c4cf63fc2b7bac814ad822ba4caef6d6b7fd216465efd0cc6cb4b1a20fe66157a8853975b1b2c271fcfedc2912d1535972fd00f4d37a5b08619e0abc563ec994cf36f5a89cc5ca6fb244d283599d42c6a21767442282a4d18e39e31604aafbe240e48fa1d7a89191120daf5df393a9b115e9867c336113c45742a90d1d4113c66891ea46871d822d95197f077e8438ddc7eae6c33dc4013562aecde7a0168f81afaa2ddbed3e2cbb4810859c2fd5a3495213b97d6e5aa7d9aaf6ec2118b6ae7c500ff3aa12e5469f2b58fdc9099eaf8ffbac111b49b913622289c81f6a690c4b3470a619ad960bcfcd1582fa9ed07b2b9c839c78f712573306a9ab454d7915315f1514053923dc53f7fd66cc142036e49f0bd58e708862cc263734ec967d5e4054c3be0369565dcab83c9fab99219aaf21a168e72584083fe2f46fc477902b7954dbae30b668db0507f29d4a64ac358d3366abd0b7a9e8ace99f9b0d16316ea74739dd47a010bd6ac51a9142122ab699181728ca1c381a941516066ef624c835ee0df7e4f202c4677417953775d5fb252bf8ba53ac17fe2f1af324a168959f81567da9e73c3bf6bda37d3d53d9b58efa392b9dd81c5827d5fcab7bb4ade73563a26d83c8a535ae23339820c153f0f79b1f9cbe2b16cda032cb7883d3ae368859ebe159c0be2ecb5b11859d27afbfab3df898a7b90efabdd58308ee3f099ece6f7fda1fae5cb6ed55111fd4d6cdd9015218d830162cbf03b5c4cac717de09dad6c0998b501a51cefb76c4b0199c58e2e316127aba37682de5c04dde16343a33e4e5ae3b6295793992467cff5e8e6132ce46e2af6747f60e4e91bcd7a143d1f42c8e9fd12c68221b067e7f8c4b1d0c30234657b7e4d64c2016148b84287258ebd1f1639bb8c517814fd9992fcca0c15633148d7ffc8c8531aa0bf43a23ccdc423878b58f71dc57fd617c185f62a51d57aa938b95a9fd85c4d2c7da5ddfdb83e14231a1800ccf9e755ec4ac01970cd94cb50681137a8f00da4938021120414caa08fe36bf3e32b7e660402cdc663e8cb4a9392e10c764024469f6fcc3b10779f0cf3d7beb160ca7638b949246e679d534316ee8d61dae3b321a37786ede9f94dde73f88d5e49aaa40121d0ee9b16e8e1c56aac332b2bf503816d6e22cf50d798e3fd4bdb003c5f162e61c887a0c3fcaa35140f3d718a220044f4c4c581db8ebb167b42c2c9ddae5ce89458a0ef92d7e741b1fcd295d49698eca399fd98089a0284c33f13e715eb19883c42af2b54995f17a5499340a20f38a109d218cd7bffeced7a1d16f3b2c4636e84d580cb8c1246ddcbaf1e7f5a52c5ea48ee90b46ff64f91b65379fae27d134b5b8e284237f96389ea2a94c2fda31abe211d02907dcffd8ab33f9a4badd34472bfb22c5afc67645f38da26ad169f699f76196f5e33087e15a38ec615ba6547b38a58ef56d81f84dac75528b5e70c88b2099715322771eea2d741c39047f5e460baca9ee95b2a19b2f5bfd988020f918e6b62e9cd405c95c473bc1b6e038ea2a07d997551488490a15e46f58f8d6fd239cd0991b6264e348e9f1c6cec3348eff7466e7e48e91aaeb9c645fc690f0a89bf8048f67a7d67967b42be31b9d53c5c92dcecf1e16c451564a2d9d7a34e3c1c7f17f71eb920aa8cf51cb609a4af0c5b6c44ad4e3ccb8346f7a86589d05be01ec908eae69ebfeee12d7d05c431c7ec7ccaa0498e899aabebca31230919861e881f948f085bd519407be92ce923ad6470853809bc4367d9ace4b0df2f43e208bd98ac18a77d8fba7fb16ed95ca128db6b52c12d33274f9d169d2f559545e40e3ec97c1a779f04ce772329a4fa09768b9681200ef3b999c6778ff606d6d2600c4651da56c6ed88d0b2ee4a1aeb7ec3cf60b3762ebcdd9111027d3bb2bd07dfdb01a9a551a338cdc3b1cf03ca36c36453eb60d66943953bbc2c10594911e6fba766020fa1ef62d7f2e1c59f7e208c1dbbdf4dc27c0a4495d299d8c84671bebe8e8647ec6a8acc6359380dd15c26d1c262371d9dcc0472202da4d8bbb828a48f3345b6939830f39fa3e570ddfd857f47f839af31fa152d97aa18092e685c6741efb93c04a31d91140140b0f34985a4a9ae4d960bb2e151a629247a79aeffb8ae91273f8860dd817c1760120a571da080f2eb41b4743ab714ca418b4645fdfbd755320d7eba610684648b3c9d25c0abc245fdb86397b1eb1ed4ffc280527e20a6cd7751cfe6aa05c836a4bfdda89ef9a98d947d316feae68be99a6e26819255cf1d20b6f5b8c2ed24df630b43d88da5e9dfa82e980f75f8e2e1033aef4831558e93bf89a103daaae10c963b85a0e2cfcdcf0787ee869cabf8c8ad45a9857fc8d6c467439ea0a0bad13b7989805b81c3c69716e74f78d8c45b105e589edd9f3b2df2b94d79caf99431b85c19f29e72e7593c61e93655109a289695bdb38fcbf48031894ac5e04519f101a7982e3c1b3bca79d49e387043255908e55d3e268da93e07c894251be04dc6ce639df29125d69e7bf6ec910e96b85c9608381e8c207ba05c33dd7b45b43bbd1c410983028498bb9d7a35e8df7e4567a6c5b497df1436a9cfbe0476fbdf72f4657593aaa11abef92c0fa8ceef1e47617abad895b32233376254ee97420970ab413ec4bbb5386b26df0dfe7851f0cdb2537c0a4e184b7b3097884c4ba7ebaa5c11fa56059cedec40f3d6cf982496566a6d29fca2b1de8efcd131889472948d020d45ffda51121d247611bb498f788adbc3b43d893eb37774c97956d438f902522ade3c18ac82ad9fba333cabd2368dc4c438d2479de45795413ebe3beb1ba61589287c55a6f5e07281d0160c0be7944b5209836b7c81dd88935c922fe9c9554f5ad6301d12c2fe3be54631c809ecf259924ec99c9dcc3bbe0be8d5f4846aacc352d56e882ef62a9645a46b0bb8dd2d5b4de64839cea783b86205b81ae419eabf66e5f70074f4ca5c12b946578fda9465008219781741e43c2ae047a2f0bfd54e37bdf22eebf5c1f7bc2cb8988c7d6a73cfc78eaec7dda51d6d7f6377f322f07e98243b71cbf2187c318b652feac32654b4476e9c2a5b07eb9aa7dd5593c867190ee9d896d549347b59619649f01ed617a01f35e847e9b29b3a3d503ef8d89039515d2622c6b1c0237da29b3648faa88d43008dbd466381102c31353b46cbe4effc4c7a87093cd0030f1886a6bad636396465789bc4cae7213643508185bfe00000000000000000000000000000000a0d10172028", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 50, - "comment": "signature that takes 30 iteration(s)", - "msg": "4901000000000000000000000000000000000000000000000000000000000000", - "sig": "ae24fa5b2e13f7ee71d55906b8d83994bb96da7b88b98568987fa7ffe9a72544552d227e935844c7b1602ad91fa0e40ded2dd5ea2d25321eb4f96be7a9e167718259e901197df2d53efd428411a073346cc9e57a23c687adcf5864b001237d34c0de91cb319ad3cf698f11fd2ccde9a91aaf2891b30f0aeaa24529c84134076b014b410029cff5d4de892bd24affeedb4972670b12eb3ea3b06fd6c91ac1517515c3193bc2953fa5a9bfe173c5da8201da2fbe320d3fd2569520a16342a30da1d78181bef31a5aa53d2b8ec5460584082dc93751ee7ebeec1108cb60f5e7853e49e7db6055df2f7cfe35fce2a2f7de367dccfc980155ff080d2d7035679da1b7a83a4df8f2d0dc105650db1b981a744338c3512ee99abb78d278cc2678add260d9d68db7e2830c35dc8a32124bcd99c72309e47ec19d3d06507ed6eb8f7aca81a9839361a89c81d3f965627582652c97b00251533a3cb6cca24d492308faf7f685929ce463cec39ae77621644e8d1579fb3d208ef0e299d11523e4b631e011317f78c0ebc1bafc8c9b158168466158b1334fc6050a582ec806c8dd882f21ffee4c884dbcc5dab1d69c2efb45e4de6fead2f6f5ec9059e4b76b2356466dee3d8e0f2eae27a2eab778bacccac670e495ddc9a824f506c5a6c2a0a024f74530ef5ada75547d124a580572299c4705a24e263d2f90f1e9121726ec267c47cdaf31fbb0c5f0a4d98230fd3c4dfdb29ba2b6dcd7c12c9197f1520c1fdff81ce570e9b3c7693fa79b7154528e843443fbe1963ed6964a4703242498dda72da2d843e2295dc633b2d6755e4cc5154856b208e02184aec24cf05a00336e4d0ee4f640592c9b24777438eb9ae28b783c43ed5dd500e2eceacd2309c9f7356a4b276dbe89b69614fd749fb4181d5d6ee45d256b48a55c892d4df68f190ecde11b87fa650262048c99b00c3e894eb3587d8905f261e47489938c626fa611bcd6d28fc895bebd72059f912231404a56a238a3062f978ffb925ae0aa03ecf3be140f1bad2e4bddf3127bd8904186832181a00a8cbcf23c0b175544c1e45d9c3923317fe1bfb29d8c04c7f0a08e3f6b37da851ace7e9bd33392fc06fc49d262d1f8b4d80174d43f8b7196aa262bf0f8f25b42e13eb0e827096f2074830464765020a51b074853cb8ee88d229cf91d07a1c02de057564d3ee5125bb443f7b981b429688eee5ffb82c972c14d3b5237fbe4ac5611784223ce00f11fbe4636519f3ddda9893c87dc942eb30660c816444b1dd7228a40b907c9b3f1a46cc166a75dfdedd6c76e38c89cc1537e63cec449c44be2054be2bdb0df0169f7be37788f4cf8f9ec5110029aca9e32f76ffa2b68db9fd0480490f894e93a66bc9870a17c1b9ae0fd477db2197a3da06015ff9cc172f6b297b5c79a4e6943df6384a737f64caea0c5abd7a799ede4dd789bac30d7846b19ed32f9669de319d67e7e4a61bd233ac77e9da19696c9c4a791fdebbccd285dd4fc0bc3af634a9556650e4c730381075050ed834e036b25fa9125d262520dd095b7811c7f4b33c82171ceeaa664227502b0dfd3cead3593b2fe80002754e00c20c65c7454ab8869e014c3a635d9bacd6116b320f487bfac58b1d4620542ce4f9303217b7455a9a0b7f92f93334b2bbcc51928d04c77e2fe376fcce692d7c36d17316f3f85fa43c994a4b672a1ae2ad8555331132b35cfb313daff67aeb9fcfce5dc440bf87062b24f9001b857b735430826fe4bfeef055a7657269c352fce093270f1b1a7241ef8543ace867fb142c2c78c4a1fd9bd094d8810f3c5c93dc9841535aaaa573b50814df0815de79cc1ff7dbd3ae869f193da637ddc5ea4d8fc88555364d612c3c5ea0230df9f75732f8decd035a98d76aafb58b5ba98fd311561aebbb4f161b3b78a6f64000972e57684ee68c9af4f708f5126692ab09c23866bb6cce9130057a99901647de175734d830039f21cae68133e00f7c0c13baf9cc8b7b09281bc2902b4f1e5e17493554fe7a02964a2d020694bbd049250dbbae5f088b6127d2845741a75249e163e8107cad459b68b52818845a04dc373d475f25e236f72f4b8cf883f4a25e857241508469a2c424ebc06450bfa33dcd2c342e0c3d170a06e0c8ac7ef2f5efdbe57ebefe1782eae6a16c9119e767248abdf2a3fb02bc9419c0de7fb8be0b8dc07afc74074d8d44cf6adc0009ba73058602c2833f4d862579e8b6049a42de92cd76da08b3b8b8e442a832b0c89238e1ecd862f629c691c5ce627e0298574bab49373710d096fd06f12c1d131f134bd3c51c48abc06371a8c48ab907aeeef68c14eab063a6d99c9ec8ec6c860b97f43fe0fdfb95b91a4cc0757ab27ea22ee30d2a69704c7526377b66b9b2c139ba52a7b5b03971eddfce00d155a26ecc56093f6834726e86ab6eb460798ad3c6208483c413562b62c57591b44ebc3dc623f01ec7f622de28ce0025df34eb9f669ac95e0c76c0dabc8b084230ba2ef1f11b5db27f34e7755656be244bd72d1816f33992cd8268bc94ff8e9cee4ab0e34083e9ddfc4ee1c5f0e7a5a8a05a0b76863f4b637aacc8d1bbd87892ea844ab3368a176859eb48b2f6d3bd89c9f4276a5cc1924792fe3be2d1031f003107fbdbf737392c0ed2aa950b00e9ceb0bd4bcf2964708e17340e2d314f7cb912b9a4d2d45117030f81d6e3746fba9cf5886c94638f1a53f0ce891f0b88a33538a311a7da219814e450cfff5e76b4b872dc53a88f3441e12df39298d90cd4126987a56c1fcac0ae94457b1dc8d2ede35c5aee0009d28865f90a1a360d435ecf71d6d0f60a978a69e5fc75ee639d15b0338d4a39e12c09870caa4bfa89989ae7c0067d8d2e142d6457ae900218c524c074c9bee39f987f040968a57fbffd0fa7989feea3589d68f0bc281cc4f7dfc02441c631724e480c7fccff312bd4f3c3eebc3966780e2b719905994e7cb66283b313eac6702521a919994a1d1bd9616964388ce9a7f39527728c67c7ea0bab7f85bd13af7c4518f7c58fe963ae6e813880019f7f4d6813c74850385b8f6b9c0370728d248764855fb8281a5e5acab688d39b7f3e246dc111c3b83c187d676402163bfc63370dd1fb3f496e4617e6503f6524d8f6ef509e54893cf70333d6907f5a4f3404fac891bc6daeb12df9dd16713da93982a4d85d26c1b1ecf2f4615008b5177ef6877a980e1caa9e9b1d53db7c4b2547f6cfa4daa908b292d2f87c7780b48b9024487d27ae1172026a3cefdf92b8866dba1736355b972d663c376aae45558156e9ada92c6c7d091a036e78978626a679eeaba0216fa0eeefc1f60887ef9e80107f9fb46e76cd26dc7dea30ef1ba91dfc2fe431f7104df08e99ba84943917904e188ac3079186aa472b1571d3cc4de95a454eeda9b4592b9724c9b4cb768790474a716d47b7c46ef9bc486cf1b3231ba38d3dc58136b1c164aa9f4299ae99b3474cec84016e9b7b57419a6353cde8889a5f48de38bed8dead721c2ef3871accbb94b19c8c0112c4d2e7b2fb1cc92a144065251292119c74a0eecc47dd8b252a44f7668ef100a5b661967bd5e9d2dc386547a2c73005faf300b147b92140460bfb4c29219b411394b9e60e20d89fd02567bf3568938a93e8025e0c1c24db2614293c5ed62b3dc75c9eb6909578afd590aa11ded16ce367769fa3c20cb5e068fc6470819804f220e2008ffb516d27a7857d5e8a8785097701d056756e2141142204e13882ade1d97a0a575fc63152a39c44f2da987b027c2fbaf41745945974c87610cee657f76c9cdb086b9ad84b401739912ca96bbfe3877c17c74a333ff98e52be971300a095c740b5b093edc6ee473b0bdf0599656282becad7e114768236f1a2facdd2d1e085e88d375be393412fc14c646b9528d09def2b9a5ef44cd75d3356bc10f1eb4b5b135bf607d32a0741b7a77b03fe44b4a8f21d2b5190b01dd04961e2b3c599ba6c8e175116af78124b67085d5f075d54f1481728e60aa4a007f7124dbfb03225b880893fd7de61dd8d31953c988d5454f973a84c4bf56f0aeb7511cdf3c24bd715923da359afd11e3f4d92b0a17bd88e8ad22e19d0eca5014d8f16d0ebbd81a0dd75f32f2a7cda47b8fc03563d5cdf5917c2b4dda39490162dcbd37e87d9ad37d75369e02ed8daf73904ab802f9b41495c3cf3e22096921e23e6abc537462ef71cff0f365e2975f3a3a5836e5a09b27d72dc4b30f8c67f33092ef288e5eaa52f62ffdf8fe7130c8dd93f99c530c0323019830220d37fb3f716d62bea22914bf0114eb0d92b9f3a2a8f1764b61b2f89d40f1780c834161e5f41f75a46c338418e5738d23aa2e3dfbf580fa7147a42e6865d13a69eb6b79e0603d1176354367cbdb4adadb398b7239862d54403118ebc5569f0454ddd954a2553820b3cc2349eb234714cc618fcdd6399aa3836228256d418f80e96c26ad07f9035b7cbbe0de919c51cd5c8efa7338483bb4480d21a770200dc0802aac83753f882c8fb555bc01c3bdc09e3d5cc2c10dfb9337ae7ee9868e34cb671a0d4f31da52eaed9f6513b825467de5f2129b79b007524f402e3940556a6c97a5b9e125495173fe0b394a6898c337999ae10683ec151f3cb5e6000000000000000000000000000000000000000000000a0f15191c21", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 51, - "comment": "signature that takes 31 iteration(s)", - "msg": "3308000000000000000000000000000000000000000000000000000000000000", - "sig": "5057aec74324b4d5dfa965882d49ba03badaabd76d7e56d1339d35893ad040fe52deb881e999796ac3ebfc749a6004b51ae140a6c0f3105c5b0824fc17d253931e48ead138217bb5fc3776f4695d4a6a34d387856372add58aec8ddd81442af399b0be2c79c2f4ac6fb0daa61bc48c1731cd818c9a421e6e61ba1228e9a66cb5d6e72cfd79dc144ba3a51849814df30c7f9434afb991d8f824d42c7c42a9c055211bd69816862e462ca4897e8661ef3a3147f362e0926fda48deaeb0e7062837c071b6f69b880f389ae55f2e4c80f4ef3bb116490035fde777663eba8a4c7e518b4721988539708bb714b1cd26da8702bce552a3b905113f3edbb6b77dac1427c0166a3fd46ec1c4ec3858c4b529145e1b9f053c1904d35f0a114cf547ceb588d5d8a5dad2880a18689e439603586ad119a04e03ddaa0188e6331dcabcd0dc223c469dc32e041ed18bbd1676c7f05b731b262a0c0a00e86753b20c9dd3d5af52c449b9c462626de5bc59cf018ace4ad9892e924f2c9af15f013710c31832609a819bf99b09b14663a9f4b0078335e81ab50696a65f8c151301cbb16bbdd3397eda0d11e5d56d62265e49a78a34e5e5bd9893fce108da77d7c17b50abd1f91fb9b7368084a8b2820eb7ffced530f7e4c78c20d1408e224ea17a19887f4ded7f7c4fad037a7f566013c082d633c3e62ce76599a294fef294f79334d7aafbb8f8b5bf3b9b58a82bdc0fe49c73f82ff86d87d9ecd2885476f9755e2c270bc01dfc8344828ccc3ceb88423e1d52285e60cc140bbe1b97cc9ea4017540e7078802207e94a037ddfdf0b681b433bfab0930fd1412c1b36ef643df0f3b3b00c05669dd77d37536c3f48a4e7889b365f19d2932e146f7c9702be9aa88f5310ad738a1699aab1f02f7a525f212bec566cc34a10d7c82e543efdad640e00f6a380ec319f1d48d8584ce5cd6cae835d23a099d91f0c42c0d27a14cabe283ba043401ac7dca1e8b42d8a8c37923ada7ce4bcbe0453055cf83a1ce54366a794e95f62e3f6141f3e0fb78eb181138b77c0474a0e300a7765603f35a2523b6618cbd08072ea8323af7a714d4ee6f64cda0ea157d52cae5775f9656aee2db5728369f9a0492428ae02efd457123f4d08d92a29a9d7943ed38b0387dfbec6dbc96732d29caa78ed8765947637c00fcc028d676d8a9981ca97fbb5f252e836e93aa8dd37000d43d047c57009bb88dec672b77d8df3dde4ac85b01773dc00a43c9fdf2cbeddc04ba3798ee18126b0c750c6d40ec0ac076b8dae0d5aa71b3e72a71603c82083267849b263251b86ff5fe1cca0ddc3747a353392a47ab6962c15e005b2578094f9f9a8097243dd15110068f941a11902d3148143cf65ed30fcbc172e7f016d629f60a584d9f4a0c539561714f1df67427331f3c8395f559afb56ecf7c5702fa34e923cf1da8280583fef6ba1570eee03dd7efd9b5add767169ca11a0eb538790afb05694b2719a9daca1bcc31de44d0d5946d1e1565d6a476373b42c9f05e01b9d39a921857ac666d190205744061960b94e59c805b0d840a140bb48817deb68e6654071e7b56696f30a27368c36377ec8be0e4088fd23623158ad7cca215c70b7dceceb220de0509bd3ff530e2e7bc1d3a9358ad13794a5fb2db6c73965915a193417cfb63f3cc53fd48d94d308f27efa2c2c096a14a1495244b437b4563a2eb65c7b906816d205e02a465b350dfb7b88403689c8930d5898f41a4268059b650237f60421607440a16ab8b0b1067fbe9460afd8878742a73914c6986ca5d45dc516665dfa4fa99d733865fea4cea28ebc12d50a4edb7c1b3cb2cd0dcd0fdc6acc6f7972dc6a8ba3b3c13d487c1c1f00883c2c1822fb58c684427b837d457e678a79c0de7e7308481721d9295dde258d2f06159c98e2f70a9be35713ecaa35286042d32e85b760fb79147f11c248790a2f274c09015d43fc33366d7d1ad713e2155600eaa5cabba497044ec99c17afa680f42410b928adaeb876bea66c1520bbce3da46ef8d3ebd6f9bbe40a4b643d1ac5c88cbdd26023b88757b2f6ca78c197ba0caf240050e6483fee64ad3dec7ad61f8f793e5687d9e7ef3bc554e69bb8f6d0ab7a51d3f5778ed262c6d32408d74879614d22963bff3fe484a83ed82a181242214c5a919f8e510064f095ec8882e18ded7dd4c3e76920200cf6079f56887fac3f06cd8c3b70ea053164b912fc6f6ec347b78e6cc3516a89dbe136350ccfc55204ca112b2873359ccb8d30e748f36dc4e9e2ab85d1eb31df27f0297a6c7114915183cb106154c7ed467dcfb0ec709271cb8b64b430139cfe732f9ba697fc5833063039a5d5a2ef59d3173447510e0f59a23be4ebc341356f2205822f0a66d65b7e0416e354d1dda7f75afb864fbbea967461f69c0fb8ea80262f423bdfef3f18c1fbda0c042fd5f4bc7c0b5d2f7618bc2be24ec820d8986a6e7c345f22ef2832797e5aefdcaa07be9f31bdd35d282eaf46d796c29b1e1c34ad11e02f89403ab899c49721be2a5e4a0708abee762150069c2dcee161204cb5bd680d6cfb340680e49f79538b5fab63ee0272fcc33379dc778581eb9b5aa9b72624eb8bb28697d6ad8f16ebb6c29aaae800f9f8063d8885f3f8293c40cddc975c005fdc67a9b79e6bdf7fef1b30e3a0c3ab51cac4ffb15d320acb9a969165fc8d9cc4c9fdff4423b9582c2ba54fd73069f1e59a3ef11f01d57e55825f87346b74cf5afd20b5569a3cfe8182d891612613374053557db3d7a8c421ce649e449f7b0a6ca7ac11459694db5ca15625181aacd2184ac1c090fe583fe7607339bdbd5deff4b4c1b82b0b2832a5368901234a627a63a67a47069b78f45f6c783ce2f782082406216411c942b9f455eb081035b70c54a13f28df53c00de9c433204c61471e021d6a589ed522445007250bc398b16548b58e54b03be61caca4bce6ccb51a9cb4c553f0b099a568ca49d93860ee94de1af05bfadd7985ba8f19443f6594de33670b7711ecc838269cc918d5ec2a5509e27682956c949224c1ffc059c22ab0abfecabae3fe954660b32fd3e3c0bd83ba0e934f78bbeb35c3ee95525aeb4f62b0ebdf70cff985feb0de983ad2a52d03d7de00caa70a7ff535339957bf7bbd09a405ce6ede82455e5ca132bb3fd473db1dd087a047281ea9c27d3c98b18cc99893ce570aacc16e4c8d84eca7197390210469d309982c2e58cfc4c3c41b0c498c02949ee8e5dccb49c1317f014f5af0acf4710631fb3e85cbf126dee44c355fb9cb1e8a0f794a4e63c0841be9ab8948224490044c4e08be105c296182e3ea14e34ad132f1be8ba30468ef364999fcd1f4afe2c424e193de17181989dc2ad074971b19f8bed0657a3e18d7329525e07778ba620d8592a5ca184757e65a28cdcc5ae975ab44f8b0b4ffe6b3e85f1194a64a053e5b5eeac4b87eb848e78b0a9a10c955a37a719160a46d52e237cbf5fcd56814fbd753941a85e20e1ae3f1252682bdbffbed04a11e3ec1d0383a6f5055b2c09dfa16f5b3bd6895a9c4cf31d8c2ea76ec5039f9f8fd1c2becc3a0f69aad095f0a1cbb7800d4b57a7546363cc0a032599c4fdc50223615503b13d7e115b1bf7e3c6bc0a2d4aadd54489327961344ba4c0f933267eba87e0bbc688cbb2aa20bd04cdbafe46d5be7405ce029d53f3c376a3225e4755195c46e25c5a63c953172c1240aa4dcf2629e00e9c6c94005dce93f8810a32df75d3a67314b1126a647bea0b3059ec7f0f4a3b31f83a16b01a31a44eea403ccaa9850622ed3b6e3b41122410a08de696749b728e12e7e106263164ca1006fd3624e48dd9b796e235bcfd240d651a5a6317506b682203fdb124480e135e9791521b61880bfad227292e2052e1660bf342995ef3ab701bc64fd575eb3c3872d8cce94356caa6301ed6091fca973889151580f11c095efe49485771e6008f3e15864f2d5c0ce96e73c432259e12ee4591179ae285457a7bfb598187fea7b08468ee34237e4dd6be18c759fd3d262bf792efc5fd00c2f93ab40ff228fefd3d10d147690bc9fe0f8153cef46624f123954bfc5ec6d91614a7eac99b9628ece91e6f116dae000353a3736339d49e00ffc66a912970d7845d437376a405ec9091893ef9e025cbfd8919cec5e5e9c8ae227fbce880d3563330d32f4cfe43e62cfb8a471eca1faae3a7b1bd40f719668e249bfc2c2b58940f6f73c8985da43b0f6b41d54809913ca8f8a8a60ebe8b09c5e2e089a3c8e1de99f8ce434abb2fb4c2529deef8295f691bc36434b36792d6912e1f4e1b728414e77440b71529bfe5430e4a38b292dd2532d6e614a7da61533062e8ff84382993a8d3764f654e90740101c08e185af2dda68d0d348841041eabfdbc9ac165385b39a03d7ef359ef9c8db393f46c5e8ddb93f9e961478c353085ede0738b09ad0a4f77e094d8e873455be5225ac4a365a0e3a943d308a208da56bfd3d5fcd439b8e73a466dc366e56d4f6e7e963d0d3bba23fb3319f6826dd6dd6a44dbb5895e707a395f646c2e02a6b8432b201211761b6c6021bfe2fef8e3254e7009fac6287be9051b2162c1c3d1db05143245489496e228ea243952790a83849ba7cbdce1e8081456bac5d50000000000000000000000000000000000000000060e10141d23", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 52, - "comment": "signature that takes 32 iteration(s)", - "msg": "9721000000000000000000000000000000000000000000000000000000000000", - "sig": "4cef6107c57d1e2a3389a755019b029002ffc1fff9d4722f8f92e9ba921dafcb20b0604257cde0e315568622d1a665746b446a8df7d8fcdebc10b02ad687d912a944761e54f05cfc113c064191b759cd8f3d0ffdd523644123542aeaad7645711119b746ad421521296aaffdbfbe3822ea3d715a4a276ca0402803a71cf4ca6c795ba336b5ef3a093167322dbd3167502444027b8b449e12ff1dcc8e9eda0b22da66ad89b01c86de493084488e126873be44c43e4cc7972ea78d524fc556b37717bf768bf0fc7374ae56332d955988ef2d57265e43768ef2ae3ff64a70037cacac2f1af03119efe45014f45e070baba1dc5f73e7733c958a3042c743af9215ae7ba3a6284626b724249033300cbb7092e4513d14a8b19b168fd3d29bf461ccd51ab581c0617b64e46d901724238d9ea556caca19d56d83a2cdb43a0db469839cb1ccd1afc705061d2e15b798569bfcafd135b51e21119ba22f4c69b205751b177354ec3c6547ca89d86a95cf1e0b4139a001cbcc5274f4eb19eee0c6b2ee749e940ac72969845563e3ed21d350f7df7d33d969738643983acb6aea290aa6b79ede572503d57a4267d97d2ca92ef2d17b104093b1242c53ed0d966ce4100fe53d7a36f14ee6335a9b85202baae912d9ed7e3f153a0292708fd3c7922ec2b43e4801243ee4a65b875683f85a071c86df08b2a999e258de58534c29722b912a78f515c353caf170b2e1eedf52910b857aa751114b7f26a3cf9122a814a6ec65f0347511eeef5094e575b0c51a90e27ed8c58b36674323964eb9725c550eff91d8ee79ece3fdec6cf9829a6f2bba5ddf9958f1c3f2932aa2a888d81953e74111cfa6600c10022e3b7a420136731ad638d26afec4d1df60bc255f45811f6686f8c81c8de97d541f4a38b6f495aca0a760f3cadd06d72a6476c02a8f61f92049ea6a5b5caf6294e308dc675b47dbe294ea8ce599856d19dcf0ea61b3f930e3fae682d8a324c0022f4b904b092bcbc0279b146cd63b827a5efeaee969b91b5158a2d0cd41266c94b873ce7e243850257e5abda0e37c4571f0b28a92d043cbe92a220170c6de589d0ed0e75ed1b288dbad8c7069f8bd3e4151c0d5bf90e9ae55e2a2b9e46898a301c0823ec14a201da94e9c0995592770622687f1a477511563dc9cf9500968e12c5b9b9584f179694a68055eb5309a01110fd8076c96cb6d57f0e228e1afd0cc8776978bc426401aa1fac458b8f3e1f2bbec589b653469a6589527e89664dd015497b669351dcea19115f55f0814a4c68f4a3c22dcdaf0d10eab6e884c6000f86ba0d8a453f773a16e2e50e85c69f501f29e1a4d8cd4b183efa68df94b98d47923dd8b2315e953465b0f65f3ad3c1d61e6bbeb34177efb27ce59c356873ec150c5d1883d0eb69c26e24a789aa0450af814faeb6dfc46d3b0309eff2d7c6d479832bfa6f9c34e5d5df4861865e64b5b03e211bccf9f72be75ec32e4140bc81dcb69f4de50d8a24896f749c356418d4270f5161328574f25650da41035a8cada3d9b630e103477977e5bb69382201fe6612b3244452a00a68e9b66b2a532d5abb29c0412f3a76e0d3fc0ba868a237c9ca392216efdd77478c49197e963660d57b96263ac47ef7ce463d715aa098ea2533cfb6bdafd984259f6143fba4f59bfe95653fa3ae232fbfd764a3792748365f5512f945d44b014f0c2b33911b36a60306f087c88afb57cf0dffbb8d80bfae7a44ea3e3ffac7e1bfc614b4a7b345c456d7c52a359bfa4bb5499c044c91bc6ac38f6ac2a39e80aebeced421ebe402782edc887da588be58815c71ae9e8d3b1644383fc15e8bd33b729611a93c40fa832bcd803913f590ce0f3bc8d3cf95a7574cb5f2a2c7368f69421153a310e776390c9535d16be57896f6e0ac8ef8acfb64c67267e246df87f55b50670dd3463e6a9b6aae11679c11dbfd3d6edda9aedf6557653ec89641d336b0b8f594a1f8dc284230200ae677092e9e7a6d129ef63997517c5a1388637eb81b134268a1be1d5dabafb6e9ac897894aae6d1720a1f44aceb2cd9749a13b7df3ffe4e06e23f7f478e6ed7e6563355fd22a52543812ab4201f9d15fb88c5a70926e2d867cfdc8bd6f4971a2b51656be33785a7fd78712e60f7b097aa88b294b1089cf01c8f7b958aed1933c983f7af824f202fbb88951de232ca81c7629bb4281a057fab0de81fc1d46b8ada37956438ee7fd8e13f1938bc237b672e0faf93e22c36bdc7cd192c6b607b43f866c3686cf532eabce500a9931e54bdb4e399b9f0b29301dcbe0eb16638486b7f96b766fb008a7b62f1c57ef8e0f5ab59c10ab055357e9e0111147ae6d1ca03ba503613c04180adffcdbb58cf5ff7ff726744bcc65df37a3f9c847b93e14c9f0dd912dad27d442406871fcda4471e8f21dc55b63b0fc702883467a0969ff3aa2010a72a111062701622f64567ad9f8a4f3e91dab436ba552ef2e42d930a71db205de921b1818ed137615ea39d16d8ad4817eb02e79e05fcff24aefa1a10e60a939c0a8235fc27846dd032f95679f9b987acd81a6f285d7e7664d88db73b2d1ae931d82e38134f2b770cb2f834e247371595f3ff78e420f281676399a293c080c7801447a4be951eca051b1858f99decc572baaadda8c1b67e5cfc9aa4e44abd48d2f3144ef92fd1ffe13dad9ce1d4f127c98119e211ca331496edd7b08bedf3c48d225409c9e66e2cc68b6ba2ee75f2dca3eea8f7af51a4bc99d4875fdc3991b300909433f4b261d36bb150faef340aaab774996ae1c6bfde7ac536fcf1df188f2125325922d0412c0d52a77a5ea47dcb9f898981a8f588440944b36ab2195b1afe613754b0e819a5962b148af4b1068ec9761224864776ccc8a7d54dc866fd2f9462273b745a9f6cb5af6a373c7a2067e42f2bf6219640cd11b04a37488a8ce616aaf23aa84968b59385d443e1a77e25e22ed199f0dba993886ef4a572d34484b965f31f76cd90a363ca95a75d175ae78b83c7f72d039aaa5e560e2ea9d0c9f29259ba6c06d7be2877db31cd9641b5ab67eb400c17e04bbda482e923263e668ffdfa92a84ea7ad18675a1e3bef85f1b9105d9fb496301bb1cd47e40c2efaf3f9fa737506d75342c400e74f1e9e6f8b1f60bbaa37e8b32a84f93efb535fb69b7746883ffde4e966410b048d4ecaa660dde811a0b3ec93fd2411e13f1643f756a4891f15a64785b0ed44a7a18154ee7d1d4cebfb41038cc64e9ff7992c9498a35e521d8e38a01f77f2103dac97504b28dad00bf4704d768ebd1c5bfcd434d6dcdb896fd28184c452420ef9bace73885ec8a87ee8e4da935ea42536e10917960784d436fca233d91b2da3cc121f89c7321d765c2b0e1efa88e9899d2e16c1c2958fc6318702f93c27c2b18ab78f65e70fd856f713088e11985c7a179119736bd14e6fa4a5322867ade8c2777130a67c74d763f508eb706ebe1fa0ca45fa80a8d73415dddc9a94d5d7459643f899e6e6b3f204bc79d7e66aa067ddbc7f70aee71a5772349d9e2086e0faf6e68f44863d7ed4c911cd3b73251f2760fbf0e672b4b933ed64bd6b4e0117db7eeb0cfabcb292232bddccc05aa9141ad70611b88fb4d35c3cb83aee710a84a3a7587122c0d2ff622fd7f663b3521616ed143da185556a005d2ab24f7d6af16acd759b3a188548414941fa2ebcb9047ef1e01840cc33a9c666948921baa8a772fbd582a538d6bea5a8b0408ba7e9db25e6ac1a2b19d5dbe479bfb4407de495d1c7cd818c58cc9ea5ed563b4f6e833f8a08e81c9d3f6a6262230aaf6d7ad0e96c5fe394780666313c10b2db729455d61f4e962b15cd524a38711f4eada4acc78daa59490c3c0c36f76039935b135128d6990fffc19f47b164fad639e6fc65921fbd4e491dc32fe11eff24ec5cd25a321b2af69ac8208fb712335c081d09bb05a587d95a7bf66b97a1f2dd8f5861f0575e0d156f7e1c3d59a0012b3dac27c84590bf8058dd3617437577a333875a2e1f0439038b469334d3f9457333e981ff9dc9273d5383e8f05249eba7b0d60b89eee427a057449802c5deaa90012d4b92e50846ee923c90b36de7f4b51aefc122e744e11b4cac695841c430710a5f261842f078284f68e49203f47f0a1805b13999b3b5a169b0ae792b33785f14a25f1158ac702ef5701aaecc7e8952ed4c7b39a10985cbf3e948084e61380e0cdedcba71a5c7065a864c412f486f510fa6f8c97c9a2946fb031e48e8be985508df9293956e7523b2a0bfbfc5564e082a94ff85e395aba4c3513fc1f55257ffd581fdc7f05dc4f014fd92c450c3422784e6a906cdc1fec67edc40688dcf1f7e77314c914a2a696112dea20296c73b3ba665d9ef39411cba46c2b66aa861f7e4dd05a3135c12801bdd4745d847d8947829fc99df415a2385b7e012dd6a5e53fde708fa552e418023735f830301813a3d7afe2567d3cdfbe790e318c9670e32b6b2d4406f1f1b03c57074add69f594e8ae8b0d7204041c309b2e52b58f82928d6bd4ec655c7df9ad79e8046d3b558decc148e89b02cf1d189a4f18171c948d974e8d14ffc83de76c334d001e3dc7de40bcf4f7fcfd191e447c8d95d80d39424a8598a5ad4f90b7ec2a515c859bbe00000000000000000000000000000000000000050b121a1e24", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 53, - "comment": "signature that takes 33 iteration(s)", - "msg": "b504000000000000000000000000000000000000000000000000000000000000", - "sig": "2aa38484627db138769301dfd9a5286975f4869810ad211d9055bee7e25029f41460d92e9b4c68b185d8033d360c0f2a5c9f0004e4d043c368ac22d395422e3d5ba1a4a2f219e38f1b300539a11481d086d93bd4ddfa8531acfeb8d418593c4142f624b881b44d306f0cc355573d25105118d6b9affc066c8910f2889f9fa45a87ef7fb5cb6aa508c4f5ad21d04742c110824a48569a1042a66a4f21723b046461c8c6b382e112c825af25a24bb26d7d874a6715dc338af7e3d4a07c27d5ce243536538ffbe6481e3542a5ac218c536c60ff0954dd5db6551c80abe9d22fd56a1486e6ceccb54ca7993d44ee52444d4876c247014bf459fef5e4b68640e6a20c5bd7ab5e11dd8a1f5527a087b97f57e9935c0ab742f399ba2eb9e7bf255d8d4f7ed820fcf5de363915d23b9d292d7a08e5cf5092516caaccfda5d4cb9ac906d10287bed5a13fc2df0b167e5bcd37768d33665c6adacb8157d9c385cc76fb9ffc53babbe3789a698d8a73fa5e110c1d87aeebfd839e2bff061d37c749c5aeee8bc63441e6ca79e1dc055fd8d789ad729dc475bb94729997e97ff08a1f1708d93612d402a64de159c26175c271d4d77114ed9176c5b9ce4234916e63cc856d9436186b137f7f7aacd7a367af9d28823d46d42add2c2dd975d23d31083424c141207a195b4212ea7bfb6da8eda7f69027552efe7ad4952ba49ac38115d93b4dfc2dbe173eef47934204f50ad850bdaa6fce06b517340b2562e468697fb84074626cb263d03a0b62a7b497ee9462c859b1d7894a543d1e261971751d325819dc071682c8f00f62153bec73cddbd5ec21f6824d4eca53dae13eb9af6c448d8d75c6d676ab18ba64836c3ecc7c20c79836a53379e809d87abc2f04f0413d10176ddb27f72936beb4d14cac5b0e684e6dfaf529b80f9b68121bfac15c8e60cae44292e8a8e0c32ebf066e708aefe5c3aa4fb4bbd7215380cedf0b19fafa11fc37c534f5c3c14cf6d28f9f624008355c1ec110159009690ec648d6ec11fc6de44831c620dec4331c900032bce86eb4ec44725667c15cc78a71f0baedb5ddc251215aa64c527a8dd8b30ed4931047b19b725d9f205a7943614850f9a619a805ba004d272d5206900846259d02c06153a0e2c109741acfb459816a7f8ec101a5e9c38b7ef9b8add48b68f7410db4359ce23cbf62507d584763744e44f95fe2233e76f32d13e660ea5d4b203bb908207ee9c621bebcbef9ad30666fb306e8ff894b2837464d3ce91caa82227d8666a3e2a9e6017f62b1ad65bdc5ec5a4c76f414ed2a15b0da2456694061ffb3296186a0ce18e366e5c5dc8b832e5bc74ff775f4d496802b600b39e5b7b531131709212980f4aef9bdeaadababd7300f75018bb60f48a9fae84f5e694f0ec6c74d3f34a77e358dc7c4f26536eb2f76adefd14e9f8822a85b1b579611975035fab27eb387602a3b4a858b17c8729bec1845b67d0725b38ecec057b0083cac04d4e075d848de5243801417dacc3ed83f89e63ba90dea0e724ba394fcf9226b50b6cb6e6017c0cc0526d7942cf5260efb79aa918c67e9c116c4183eb8068e94f25647923658825763acf820c56deef853bcd33a0c12ffebec84115e17f675b9b25dcfdd6cbf0c0e3a1feeb7c387d059b138665f70fa762a42fa3d9d360d3063b86e43f67e54c1011283238cddbf4d054d9126416b8d4c9116f8635e8cd19c2f202c90ea4470d91bd737b8032d4adcec9c98983f789c97852c2a60221a78b41e3ca75446f2e1912dadbe04b2304291353e32e73e1ee66e698a9395c0c93214a2865661dcca210b6d48972fe80368706e041eafaf9f7a96810e395f72c2ff9aa7e5d5ef845907184f224ba37b4c186c248da8bfe403df87472107da32ec0c0ee10ec6c867341ef62205d879cbb9ded18dc5d978ba96882b5a8ae2df769eec25540a431059a52176cee356a6e3c173c4ae79c3694b1af60ee164408e12ca1131d3475eb5467c7a95f8a794589e13548cd8b11c126244008c9424226929a6086879dd5a4bda4a82f0adc2d03d239fb99034f497851c204dc08961782fa41449ebd588d27b4d7da94cf8019ba42286987bc9d8cf0677ef6c45f0ff79dd41c3895912300b70587f7dd4080a65e81f5d12b0ada473bb597149e667e43804526fed0c9b75ee2f9f09ff32e87040e145ef779c9aba90f13f94c514f6aabe7690d51b6835f3e405a613c8a1e0a657cc259862ccc5a41a514c9ad0baccce1b8142de115994847b98f20ef8fea606a85c770a9d49cb1d37fb701119e6515307b62714d385f3854d5e0b16f3b062afd35586d71b5baed356e14a43e77e0993b8d30084d402bc8f569c5b837cf2c25e6869d2183daaa7553436cf48599cbe24337eaef1b44a8695d5a990241255579c564bff1399258090aad8525e0e5e75f734d15c8331415fe48d776f8d50efdb10aa72252dc43ecc13ca6322fa06d750cc9b817c879a2bd545ebce4b9ef00f2c1cde4d4c7b38a3c865026af1d108f66bb235b07935045d9e86abb228f99b94d82dfa098e680ba7af3e69a2e7ff1f2454f6d8f2165d7a05744e0ee3bcbb320a8b44b9219fb0d81a2127f112eb8d32c20a4e365f2037815781a0eec8d7d87b665bbe3d4c5df6aa798fd3c66d74330c78551d96a237e7125f79f9372b12828c40f7cd9d1ed7039635ed18ca5fa353a878913c9b2cfac7c9d774535cd6320efd7c1e6f2301ae3ebb3aba0d83e46a80a176109078cd101609898f41494da47a366d16848f3aeb61c6663195e1d744e18d284e38e8e303395a3aa6e11e55aac90f011f90a7717febafa8f5be44d033f3f3878877823a10b6e9721afc120f1ec60dca8df125c3c4d052e1afa6a921b66d4e2d00618a2bfba3e7e4fb3c15518ec5bef7589d2368a10af77394236c7061ccffc21ad67af1c9ea74d82a2820b11cca55a156927a677fbf57649b735d2af79ba93f3883f59aa403be37cb84c6b00c4fcd7f28414b665d77f093f4d6c0e7bc5629473ea1c31afe2c1d1a2bdc6459c92d4539d424436113f630059b9d90082ff9b3629e4c13149d6cd92a78a5defc5846f03ceeab92c88a53dcd5f019ac69aefa553ad4b4be71b08fcb7fce4c6dedcf046a09a7d3e1d31ab3afa543026dad8ca9412294004edcd16ae39c18144abdada4acf209a023811f5e60e5357a18c242691f990045652ef63bf86dd8d7f5d05f4f46b4276f580d1170acfec3ecf5426612938e37e65319854a9e0931e0981da00dca67e8fbcde6b94dc54b30dad04f27022aea635983ec8017cf389d482ee6c104c06ef7cf9273a9902c13c4a3f79f88d85088cfcb32396105d62f2308fa419ef1f29283ffe1becde3a2ca28e4b14532cf581d91c311beb4b41a9a9c55ae753e2e28d222d0b36b4c290a6f1b846cee14f03ffa91f3d743fcbf37d5993241ac2efb030e2652622e65be238cfd7e4a0b5e3e40e25e6eb5601120253a08be5eebd20f08af1dea872dc41b305aec03272561f0745aaee1c1b069acc0e61b16f4effccddb0086154ed66b98f15ad58975c4604ddd96e2fdfa674fe53c5d226d376081ae0bd2283f7106558a54e613900a569e799c98e4ec2f024c0d2b15cbc14bc96bfc6094560ec6c4cd9b9f879e3fe74a70c0d3ddba82f055780be7db1ce650cefb313618a2a5336d9b1168fc605518f53708afd062bfeb9a7f66338115e3213e8f4e90864e10b4b3a8eaed966f99240c23a7ad527892b3a25e1a3d656e724b84c46484ed9c0c2624ce62c46646b13003e3eb2c8ac1e1e307f40a3092d96e13463ec1bd75d62b679f4bd1a9e4967323f16c85ed92066b283b12f49fe50423359f7db6c0df64e04568d470c480681e6c6df4fab81d896e13735f3a1a18d26aef3e436c86308a4c184b709a4918670b870502d30d44861d360a88e4bb8a693659208c2c82da46a25dfdfbdc81e7c0a5addcba03d2872b8c24ab2e1761e2ae10a67dbd724fc4652be47650ec912819b70a4d628c4c16f630d24bc5811ae66fc1afa55234d5fb83271d5f8eec99fe398acf3275de23bc002a7652bf60c293e7c04fa6e10795c00e43743050f138b5422d4c09030dd12835a4556ae423406cda8b4936ee4e039324963a1fbe8768798c384f237f7b8d23cdc75aefc035c0ce65fbd9f8eeccf126f37352d9c75a40e157eadadd12b64b582bbaeea63b50b20ec88098e54623bcb373c63eac44a290a7ff8841a417c17bda385992e3f5b952951884273ff45b94067a819efe5cd90c7ddf935c3636ee486c98f67be2eef9ba4cb10c701b308861720f54c3017357e9aaca6bb5fd826cb39b8e0d908171963bd068a589860fcdabd8bae591d4fc6a6cb8bdca9a0380b3c70e49af9819f07100dceee2174331053b4878e41fe06782b5421ff93b7051deb43a61bd5608a881423940222f2cc2bf795721472b2fd714ca7a59373fe0e1c3c9dd5dfb97e345a250f63def1732f19085a5d1f50bd6dd7d26b22bd68aa239450d21d97e85929745896d3adce416c9aa28db0c3bf104a246f70ec5e24a11c3618280cab7bc6faedfca29eeb92c9ce708538f796469966ed1d5eff70e274d5f747bc5dd6d8a99c52035666d80a4bce2fb525b6b7eabce0c1c486e82f50000000000000000000000000000000000050d111a2026", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 54, - "comment": "signature that takes 34 iteration(s)", - "msg": "b502000000000000000000000000000000000000000000000000000000000000", - "sig": "fa54682a8226fa50a7728ee9ce8aa7b72bdd00a4f5643c4771d6547275088fa7b32042cb5441cfa8880779a602c32a536236b3be35a6e2a13360d4825d52f511252d6a3e272b493bc73878e0e3711360b5360af83df3f57570667d866c8558b052c540027a690df9eeea1135aa50546b2136d349cab85dcd698fbae1aa6fe0fb2eec20f3ac4f004a55be8510c4015f74538fe2e695cdc154887631dfe924774a6731b65aa4349fa16d536c7e9b5642966606e3fdb271779ffb0d3599bf958d3727fc443a6a190f4bb2f2853f5f6d773dbafc371772bb3d2b0e88aed601c9ce8ffd60b2496315f507bdbb50c7a309fcd68d85fee1f5aaa9420c4d2b52147d7fcb38026e21b5c467af3ed4b16038f2beab5f54b7c134571c079dbd28c54c6e06505d69b6dbae1e720e8a8bda189867861f84f5f6fa39f9af2cac8c6153bf1533b21f1e70360baa33860353eda4f0ec700c58283e2a3fcae5f0053c395be917ab411b8c2bfa94d892bc4fa424f6dfd97f9fa982b02e4fbe6c43b598eba769629ac66c3cde157365053fb6595982daaabae610cd3458811da53cfaadc053d8af104896e438d7bbdb025c474abc2493f74e16fa8ba563ee0765f4a06dbd874748302dd52df925df631e5bd5a7e335909aa7f8e7a65a7db7cd1988add9b9f34a71e3b735da6dccb4b6f6787af5f1e519e24a1e15c5930f43626f5ed734d4c442125896aba42840fe0613bbb8cb68325a6bb26bf1bcf14a055fcf63f11020ef7572de02b677315a6c83a2d0bceaf049e91bc715a085a25769ab9c9f4b6592a41c4c7e212c3380d723d3b4da5d9baaeabac9410e32eaa58f38facfe1f7438e4eec3ce5091a1e38f98100600dcc215d3c8ca850b46d60e2b941e10c66d809282f9d38d710a9202f9bd9a79a62cc30b32b5a1af6f9de111bee6a5bcb65e9125b8cfabb6db6c750c7553d6e3975be064feecd24e26c7196e931d8b1ce48ae6be3977db6d7eb200aae36191f7f0a2be3d3d7c9e760be49c8fb0b495338771f4b1676304c850db67d24422d7b153a4c34ca37a0ec287dd47739c2295dddd32e5809afbab880da22a82dbfd4c0041b0b8a6b9168e7baca62a6499fb621278ec25a81104eca44d2cd0165113fe6c68a56fc730ba9c7dffd039c978a701ed9f6acc61e39316ce53082c0dce04b4c0cb305aa53ac14befc5f65be4fa4bbdb79ab17c12698df9343de0b4cb3feb355cfca73529f36198d21da56bd343643a0d27d040f2bb7d048ecbfd1fc18b4bd27217c8532d63b47fedc445430caa18b2007ca9ae7fe9dae5bdb0371b897a3def628b0dddd3ba9b0805056caf5c02b7c3e44939b34ce646be0edc1289daa3aea0260643d34ebed8218aed531bee5ff772f2342e96e27ff488a5d1afddc3c5094a7f94f01c70ad619def58612f767cb21b3c742c43e94ff21b4f30348600a766e0f66d418b9f450e389be3ed10d3f080579248bbd7c72ee02985424c09c95b8af7229cc57e6dbd7bedc4aa2b08259db76736aa82bed4ab3198f748593189b0f5ddee1b1b8164f1f82896b458b6a5794170c056377b40e758c1d9f16a4b060f590d0299a3d6e8bb4d9046b194ea49051dba75771159d58d67d88eae6cd6d3cdab259d3b0422b1d1e0b40388d7007f73f3e1ff362c7bc785dbfbca4b4d007f3c799e8f4d11b806f26d82277f02ea2a61fa1cd5efac837aa29bdfa19cf00117f72b67c4df10a49a01efda625506de427d2ab9a514c9cf201ac86fc0692b66063aeb86b0b23e4180f6eb362b10a8dcd44f96983d5decb7b463882f7e0bc455c34998c65706e12c77416052bd36490796afdadf360ad94183907f807113b8c0533ff36b311ec6f8a31f1fe36f822ce27a580d2e5582a9c2991be1b43d0ff9c91447932ca726e57ab3ee076319eed5768decd05aa7ee857ec82b9132556cbe968f6ecc4013fbc49568c8c779d9a6d9dea52617e0f521c46d4862b47691038d9c36adcfe17a24a7f44fbd87114ef18bf1e1df13d15e060a01e2ff31c7b7ac4a355b0f5a3e98344d86c9510af6fdf934346e0b8c756fc5a14ee062d190ef7b6f78764e2063040bd09c4f7e43f1eb64f06d2e5c30b020d6c133dabaa9ebecad1623e3fa26bcfe1471471a6517de61f780b3082007676e5ff6ee9d5f31afa57c9faee333e639efc7761b0466f4c3b096cfda85d11700a4ec5db2deae29042dce8b74db1132104d9b9b0ef72962ddb6c23497bcc76e481871c322712ad44af7387a3e9498fe9a7c86ff73a012a2c5f0f492dc6766062cc296472f4ee671185892fd0704e8fb0c594eac2b817916ea7eda1822544a7ab2c2854e3b0c578fcf0d0b4ce731932af21a293e0c0e06fa5ba4b58dea2695fe4acd9fa6f7d1e59ec3657fc1f37e73e8e3536d7560bf502a103703cd815c9a10756da5d9e651234ff8d46f5f97bed85b89b6fb9c9c8026948d46dc5575679e8eb6cef8026aabb9a648fc87cc5e0fb06164cc22d6ab541caf5fbac8c6140d0fcb57719d45f22e055ad82b217cdb07dc986c4af4c847a8922be5d95f5367933b04b805e8626e73476a5da495bde018836ea5fe9cb34b3abe0b65885c83e918b5f5eebb53a962ac9e460dd6fa39795c68320e6b5f5e00638a1f18e40c3cdf75cc82794bf5f4a524081403894221f469efd48d460a8915721bcf0d6211949245cf7baa2f1ac65073409d9c1328e44142c9161ffc8d31ed8a387cf3dd0511cef2b61622de0d46d3639143339b9b6ed75cb5fa7c95011d878bac8b1be21be2e6608f040f76fe91f5b6fa92387aa081687da647712fa3b7b5e32ec2f5d22920acdfa5557ac8c071491bd4518c54f6d93bb8cde1a38f9dc1145af011c309c87c5b627690958fd466a4e8c073796f1cd07d844902e7e4eb56c031dd8c0dd6d9369c2eb4b89e4a9900bddc8114463c3ae2c87ddd1013b2defcf705ea746ff48d2821e5e63e033f4038cd842de7c838d9418c8e27a8dcd2fb9b88d8a0d0ba9c454d7a0a167a44cdc878f3274ebda260fe95a031c6d8917458d3882e11fc5363ccb034fca155ad29d622be4a047b3ccdffd362a3550c552a1b698e87dfba1774e527127017fdee76a91525993ff46b5eb072c79027148420fc958d1cc62e39dceb827dcd9baffcfc8b13888072827b0132cf943e31c71131e602444028740e6771a49615fcd00cf34ebf09bbbb2ab63b57803db54a1fd9c49957971d308548c94de5c5b6a5f345050ceb75708c8aee3c624e0d8290b2bcdcc918fbdcda7bc30d3f5f5ce1fb2d4e6cca86d6ec163f73858b84265baeeb0fda0f40e7bde058c85a2138bfa777c8be45da1c2b7915f94089074f4f22c0c1ecea9375ee2bfc23f90c521b8ed51434134abca11a9c3fd019244710125e9b7dc27661d23bcb4a40d5e87479d6b07ac86cfd91b5d89e664317336a2a6a80ee88b7b24ae1872bd99bd372d06cc21d835fd2336ea2ae53b7bf8a1c14ef724eba94e971524a1a290f9b7f265665b6195ee20719648b2a4a4a66c705705cf48b41a7c9c7f16bc2ae479ef1d5c23a4050acbdb0eef0a8c792f547952170a0b869f9b5066c06c4fe79d22379a5f8145c700049c4043215f60a7433955b2d9c681133149d845de27c355e1dc40217dae2c0a22c7d9b9e346ef585c35fd8cf96ebfcde2a7d4b7445e6c11046f0644ef7619e9c4bde19d33374061c7d55434249f4aaed4c7eb39a86f9d1007520d048301c9614943efbf9e55e11ea0b4462c9995c430ac4e7c3587df2a9f6d374580d0dbb48973c909615fb846705386c55d486063f8a0c9813419c9689317119ab6b7b6b9b72a2327bfe956859f8e3edd2d0e6a2e3446adb9c130fe0eab8dabaebd7593f9ca7b50df7c0f9643415b18f3c18ae06ec6ca1d39064b3bf8d8d4b841970e3c38c4e609fa7d6e8a938c371d7e4872ef88b088455715c5766126882cca88be8444a951b3984e1e24e38f87cc2d22dbb4459c258f7f6d9c4c70075061ab9c9a60fb23c0d4f5c9170c3368795acf27e099d9788d72e488742e04f779ac217f14eecbb4e3a41ee5d1b7e174b6df258ab1d8851c321c7ed74663e9f836ab08d8a5994ad7ea1be34ee3029b35550d653de0679b0d385315621282342dbda3abd445c695f67ba506ff9d4812a3a70996f26c45d71b9039ac4e4868047a396d838e3a625264e23178591cb966732901cf3960f0d83d4659b5ecf84e3948efde4413ae675d21a25e74aa780b3d4500b8ebb14898e9b8f332ea4524c7a560a630c049eb36b4ab1b4a77c9eb5755ff8a130786da3292383bc378ffedf2a7f3ddd8bdd5b7ff895608bc0c79ef3360c958d8e4854ac76dac7992bb69f6515052c47716a19bea1eaa0c0e33fa4f24207f7b44d5b48ed9ece05d5ca9d728b740e427823390c1d0d7998ce5edfd989c5d0ac351990cf8f291de748ddbcbda698052ee52cc078e15b7fb5360d890653c7b26458d0fdb813df3641f7f67613f5bd951d98128bff3a92d2b2c8b65adf282ff168af584730c3afdaeaa6550564655ad7700e5c34c6f74d091f1b367b210011788ababba86ba2e8eb6f2776c3e275637237c17250bbe31394a5a6f850c8ac1c9dbfa0f162b2c5e5f6e9cbbd7e2ecf72e7ec7d7f1f41b4d7b7c9fdcea4e6a85a100000000000000000000000000060c191f262a", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 55, - "comment": "signature that takes 37 iteration(s)", - "msg": "d20c000000000000000000000000000000000000000000000000000000000000", - "sig": "1f46df1c64f499ad5738cdecb7cdb03505cb055d9ce542e947092e56ff01ec2969072aceca72c59d51e93f1d7ce7de2540dfc1b0e2031597295ab90a154fa59e625c00ac9badd3eea471f51617673b9a963c8538971984ac28b77af69a6c1b24ba5ad2ed4cb30e9e4393e869af84d39146a2e2c8a31154b72d175f35da837f6089c2080776da166aaaec56563a220aa138e9c21b4d66de9490b8a0df1e80ac8521055bf24866e529943f65052f5be8765e1d340067f0172c33f9c68d10bafaf0b88930fd6579897d94ff21d74b572213b58509a29b396ac1cd0cc00cffd675cc6a11ef51dea3093416c12e994f42f24ade5725903c7886729d240941b45cc4089e66b8f995ca1106fea5ad912bbd3c5e47e1819496930eb044a273eaf6237de39b291a7d1e6192ee01f05d487437858bd1aa182ba2c04c894d5a5165f6336740de417f065360a70dfcbf4f86fa781ff6ee799a31887f37e9f7dedb12b2ee5508b28ea97ffc9cc87a0483c8d9a1334f8b29e3d9acceadc55e140f763a413d5e1c5d7987eb5abf3cb9e68838b2058e2f4df650386707b62b9cdc23733d5e58fd456f500a51746359378506724b87fe07aa24c192f56499becc194e128c9ae5268b22a6a22a5c5ff197881e880a13d52de0e5c6a7ab7dbbdd07d65cfd1806a84abe6455c4542d0f832d42fb3f72b6b26ebe1f4c306ffa6488509c93faeb7204811188223da6e932869703602b834aa1a3b65dff320f540be23ecd843b1e2901965d5805c46c711015a47ab82d0b1d9d12fd9fe8c6be4eaf89df00acb07a3d21fbfca442298f70ea4d2acd8edcb2f9e88c3c02ffb667c3fc0e2b2e778b908c206e35f6f3287a6ef9601f6340e037ad38a5d1aff1bb2e50472234a01164d5e213dcc19657c32174fc89fedb70c8e7e4a4dc613b820f43a57ffa04a9e00546f2918e1381d9bc2e3b19c3f79f74b998bbe4f08e47b79b536e737104af435b96a7912eac3f83b36ad6bf77fd29110dcb1cf6d4a2d422f26af1d77507383aca643095b436eda471cba8d3f97ace49ca048fa5a43ed7eed1de5c9f591d2fe1bf6b99d1978bd87032e27598356352029e5a16d280c07e6e702ff7ba900416a7246f0d0b0ca6f9bdee5686766a6bd63f0298852d26f6b9e6002b5c2a704dc6b82a29accd800b39c46dc534c82659bfd63c82d1f9f291510078a6682cdc1aac22141549c4d9ef2d6a5843b12e376dca96cafb5a359612662946e81ffbb6abbadd985077c9a1fe81dc9d81446ce554effe92f879811932a3f8ef2d2b5619670b9d5b9cc6c547b655e41233a618a3eac821c8a8bc427f913ae319e6339ad537121ecf3b22f153d93331f66f594c8b71157c321a753d0b3aede490db20977019de46a0652f9dfa175da85212599c5726fff321cada571524c6f2003af70dd9fa28c497a7584078a23385b88a08edccabfca847dd45eeffefd30f8f4df276486496b1fbb1b7e6d49921ed0f25aecebbfeaa9062b47b9e2a773e644e2709022f66fac061e012cbcf94324814d07d7aca6fd165f90298b70efc207c0367fd51f1f172df7d96c46c9ffe72c87ca3cb42e6bda26e2352574c6d6341c6058ea7bf9e5614748382c2047504bc97fb4f00ee120c8d17a2802f5807636e754781b325fed89cdbdcb41b279c11f7a0fbcaab32f569f8e98204aa1cc04ae6fd1d70c29f1a3b286fafb5002f46916094c36de8b8b0a6afceb7103da9522e515e0abd3721c7402b12a3cc93e31f81c4714a4d86c3215b8dfd201af03c5dbaf5f41b35525e13402d753fc371b9d46e8d141ee0dc7a04f382ea1ed257579d06cd68a0f675ddc5137e5afe71894483f1c184dda00bb12e62afdcdca6252065224476d28f3ccc362dd443e7412d21d945a20c4ff7f11054031351fa93647709ddc89ec667245d2b0feee0522bea979f3e077ebbf2d6a8fb861de7ec495725374b19bd3bdc0108b526caeda1f946d022651a1b05a71ceb9c3bd1eda12728f58cbbb27af266e019323a3dbd149188bff16f6f154e4ecae0f01504afd8bda993028ed478c7eca673aa1f33af88b5de67f1192c668f4136179cab9696b44173b305e6cfd30dc3f42634524cdfeb2d77bdc8d2f247af73c774f39f1af9745a46c33f0a4714eaf6f7f511f437b2283596e8aa6b55d3bf5a94d210f54b99bc642549da972e94dabd7d58d0ccf33fc53176afac3a0fbb6c653bc2e56351adf0980a14c312c38ec6c9160398cb97657800881c01eadd0c8030d7123f6982201d1eb4277b7d895246fef315e39996064ffb115e3b3dc50cdbcaa6129f6ddb2330c64d57e6fcc2eb83db1a4cfeb73177187dc8323888de1abd7bd8bfad2d184033292c21d3ce851d191535a605e3298c8c88f649b819848ad76d4b2f08ae36797ba54b5f3dccb32c8258a38146b6c86f175a888117d78796d7a90525aceb8f6986e4acec13281915f33a4207e1f4077d586c6b686ef10b2d16618aa841fb817df37968be3099a27de57c44ba8f8e55c0f1e401de53b8578a733e9e81268d462e2321af29aa50f814dbd7bd05856d890008148eee2180b8870ae846e07e48a6660202a6bd35a7391821c550e3810fad442b589ab6b3e0bca5d7858066260776148a778c3b9df8c391b72451df0c87c0c64491b2e5bd4e264575cf047cb82f20f95ce3101d92aed4834b98c8f0e5c81c8e6baf0ab3de870d9207bb64b6b99a395ae2de378f8ad233120a968e091b7e1aa81195284f3e9152cf211b1fa26674307a57390e56cb812e030fc50c9d18687f67226245b70e60ca87e9ccaea0e7d36a5d951a22b374d71a1b89129a0b4067c60317fe9795e4a0b41c4e03c3314ab9437a1670e4bae274c2e93197b2d7af9bf501becc0545707659ea737f9042d7dd711ebe6a801d34b3cd45d7c1275fe8559bd33d9b160744d6107fab7df7f419cceef355f513d30aa82e2249857bd05bf524273d46b9e906f557e02604210e34f1be3213b121994fd3fa86da4c5c43fd4bd213e76387868e7f3b2ade5bac9ada99c54d0e948520da7ebbeacfe48e2a8113d000a9ebe5c14f7dac827393a7ed2a5eb44d8a33cb2c010cacdce5b868f9ad8ee93183fdfa1d05a2febffd902b68bf192682a0b5a418bdb900d86365a25e5c11486ff4a2547fdd7cb24839c3bd6d2fb95ec390416dee8d5b4a1993ceef53a5f5ea77357674c7c0a27f78c483925df6adbb5c49074f5cfa660969cb506abce22c764de475ff9c41e064035c48c088dd6c69f384aa76aa21e2c0e4b38f4405adde76784b0cc331484cd3c954776e63a5808f7f973bd73ae418f8648a02c29a8033214099e4e65ffd33066913bb6fa1d5d360865bdb029896a8a5d5b4ec4ac8953e6aa02326d7da96a9067d968ed2e6cab00ad00eac6a296fb48bd16acbcd1acc02d221325e4124c3f3e69f6b0b825ad513abc0c7fa7899142274e2f8bff11704e45db46adf1c4c93754c73e8eb6267e5f69cc4c24b1a9bf1039a39e8e091d944c2981864e78290a87d9773a43898de581e26fbf0919b8a7bce07365e1df475fe75c3ce9b315b07cff1e3cbaca2b16f41309398eaf299b11253a015dc3f067a91157cd6abde00d7c69e9907f6c1222fed29ff9223f3761d0c4de8bb07ca4637ae5e0fa65f22a61af6dfeca7f007b28e764fd187ab52c158690ff734a8dd5f03f202707f27bd271ca982e5e39ef53c18f4cdee8a6285aa054683974c85b52ddbc3d6083b2d88adac9e2e4bc708f05e70e0f24d5b318757192905cdf1e5211b48ad256abeeed49bc752ca5c69c8c8481094ba4652a0a0d2c824b16048907b29c231e86852a806ff24014fccdbceba284ef0a6814696a2889d64c5e750b132d63f9fcd693a201ade06b92084107c6947efd9be127a8fc4e871cab766cef81aceddcaf89b50ee6f17652ceb878a66ceebceddc72b23d3c1f22de6056e27d56275baeb0c8e782151f843b4a90fa5f7bdbaeb8428620882db8bbb94e267961ad43d9f0649aac0a773e714fb18e5e7b3d2be2ab1b53e65bbe5b22ea43a1c20d56cdce27da15758d83d3b39536341dd59f6a174572c6b182bc20df8cb5739c1eb3cdebb72b8a602ea3b4e025a9a150097bbfa79473d056dbdaf2fc2b587fafac2b58b1bb452b2d62b815a36ae59a5a8902d7c63c125077906b397a4c73c45cffeeb57efd12c7fb76c568ec76f5d1cd0b151d946275b4a94d4908ac6ae08d272ab81acf1a4cc4645f299e8c84e8f0389dc0a625622a6a0f1d9a5080c918d2e1ad2b18ecbf64681d8d2088773c306537f8d2bf2fbee5c372b315213a78ad3506dd4b6a6cefbb939b6e0346ce2996fc6c2600d08760ae3aa1c151cdd5d0039bb071c71a70c0eef8ded0148e0368c79988c53c18dc8aebbadf78d6bb69b660f86a24a3a06f78445e00217e545d8e3323c2292d4ac683efd04a9f8c2c3a383acd7444d7ed39474102b2a436de7094bac40028acd4fc9d100debc4b9d5de7ae508068dbe40a7e71b1de99522252fc9d309f62229a5cfd785cad97b58cb7a5a5f9da5b5a50622f72519d1e6f2183b1cdc25e813e8645f0a541c0a3984cd6d551bf0e293239616769a9e35f94a1a4e8f52c2e5a98edee01020b1012306093e2465e89f60f4a51bcc3f6feff00000000000000000000000000090f151e222a", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 56, - "comment": "signature that takes 39 iteration(s)", - "msg": "cb0c000000000000000000000000000000000000000000000000000000000000", - "sig": "6570319fc14d783b583fd81dbacc93c9f25e209c7e2d1db45fcd193534299d97fcf05beb603478f83fdfbe3ec2bf9b808b20c98d8d72b717cd72a5185c448e725023a0563f98943926a79fe5a2a79032e08c393d2c5a05fb93c85b56f13942ac010b90048fde95b3b4fb15741143321473ba593377ffdf7cd22d84a626259ab652002101eb3d86125ffd59fd794d9c5a728d7d4b5cbf1eb65a1d4d8d81483bd3771d53b7598495e12692db46e73a433805fe7fda3baaad3bfc5c0095fee660914c85380a0663f0d6858a065262d2de624c46d94c1604f1f168ddcbd2bf7b771c0a251b9bea65c3526e1f12d677d9fbb2a65bd35050fd2d64c8929ae862b89da6dd0510f5b4da25b9367f0cff726c9b3f0b7db05a1e5613e598bd8ea4306fdb17a7898c5f8f3375a8cca6fd7c1621d1bb870d12fe3be62440172b4cc57f7aa8d15acb44b2ec4152a65a36d098743ff64b8e767a4013b089a9079eaa4989c6982f84f4fefdae1ebd3ed204aef26e367bc7a9ff803f0c11917b0aff5bda98bb4fd7d594d1a6676312827fedb48261521c891252baac6beb46bb7e12952b114c13b1e47b42ccd108f9c9772ced3341cefacca3b7baf0940225cdbb03e4a1c1f0a9805aa6a5e85e6772d7c6feb44a0983f20ef222bc2db11f9a755d5033078bad4a1117c16159cd963b2e7d5ec56918399e7e2bf9a60a1a9f5d095a136aa9fc0cd559c85fb2b5020c4cc03fba4c34147ccdc62d0419c5913515e9b21404d908f2f9298be61437222b3b54d4db7017fcf063c03ec7540b725e5c9d0c3b9a415c7ddfd795ca26eb269c194393b7f6aba85600c2314a2d70865db05ede213e128e63fc9c165d88b4b72c8ac5937127a1635b35a6357d41f16eca42233986be1b9cd2e01c0c584371b2d7a75585b8e2c1fcb0ec296a22f81e2d5abbb57ce4cffbcd0393bf263e2a9bdcab358765b61e5885bae17e58a647fe50cf09cbe6b84461bdca74341db00c592d6ccf7ce5ad746d03b822344fddb152a91c1bf17fcb75c7d0fd60fe208650493d5353cfa211d95dd4d516a5ed6ef5a5f53a83f44d45dcf8cff27f7fcd565acd684d7bcc3910c3ffb2675c52735acf3796400de88048f8d1df93ec618fee34027f2e45f6c96a67e43104eff82d53d7c298d15758d5fd2b466b9a00f7ec438dec6a35d6745265250b46c7fa4c1c3d567d1837debdc1c72d0d7e340b03d3a3151037e9c3137af1b80bf266b8282d02bfee94a01187aebe854659c426f12eefdef522c050d8b514255840f870e0694fb191e918b5ba89df01047b8f4f7fb4142f7942247344ccea2e724fb30e75f824b9b244d13b4ec29b8baea39f494f5b17ce1bc8b3584780ae622686a7934249131ba8165473c9e064c0b59bc0db04d92784976085a389c04fa2fd6b15f49c70a59890af0ca86f05db1128e39b36023700919a89faf4db37d96b29b73e7732b37866b90455322fadf4fca1ff26fe9dde33a1e4645d394f24dc38541f8fd7a21e0c80ba0f7f5081874a677e337c802f5069121d4df8079b9b1143cda5edf2ec1be98f6bc60fb26ac20012ce73b3c56dea37cdd25ff02398be4dbcfd8f681f5253da1fff4b273634c1bb6f3ed991c2728c2aad1d1d1287f394f0f9024fe4d805f4ecf059bdb4786c4125af37e65280fdb8df9206186df5870b48cded097379d3c3f23c0c5920cf0f5b9abd7af7d5966a204be229476b42bec5ca903df94dbbe1e89941ccf36d7aaaf4beae2ec1e4ff5189c4525db0e9f30c11dee8c8673360634d49e59f928df07481754df3b0d4b14e30cb596763f3268d1106fc571705c6b94d7ff3e1be58a68bd1119910775eae6e0edc89ef7e3a4fbbbf71435c9ee55539d45ae764289e673d21dd62e38d1e5ecff6a2d76462454a5f366a017084b9b63ed39379a15d1088c2acbdef377e78bd0850eeb278fa4a90154783d64657ce67ef0bbe4ec673e2aea2cda4695909cda72ef13a8be8fa81558bcefa0373613c74bfbd5abad71b06b98edcd4383ba05dd89261ab86c28b8760e68761e928530fa733c71ec1ad2153ce8651fd5cae23ccfba0ca792ae0285421139b49fd4e1e3f6b7e84c34b0ce9e8ae3cfdba198f325ddad28144bdc8d04beb45d311f960d1e0e730180b4677c01d3023ce79416e94df5782bd27a150a97ddb7b4cbe7feaf30733253d27f6dcde4c50f912fc1b01f899ce1dd3d48152e67aaf1d90731b3d4b578528538c8989f9f76911b3bdc6e36d9894f781a0c4c74edc0a4e102702f66f1c8261a92b38754291726fc8eee9afadcf4a256745884063faca94b2a8b98ae96b0581ef2319ec9ac54619ba66f2412e95d659e7ebe39a909408e5ea7901c5bc27c74709d0621597e9e84ac59befe675c51cd075a25efb4c9351baa7d3d9c983b27ff1595a2bee73952c7c0b6c9fc252c8c7086402ff025c121b92c2425b3428b743496455954d38ece2b3964a9fac4457552388127c012a26bc88bf6866504568ad32a742f87123d61525ebd1f4109324e3b57640052563c9eb9cfbe683b5a325c6e8b028b6b9cef425d895ea902031752a5b7ff96a2af6ee1bd719bb0581a4a4159c0c58bc36e74c7360051934433ffde1b6a49f2c04e93077d8231865b3621e272b29a6f50f7a2d059eb380b4b43c3155d7b4b2b6eac7da5b135ae5b419b5f3dff09f68251bf5fcc3e10168ed331f5f0d1e0fb51e5ac777b2eb4d9a2befcf049be9851f791a6f059414ae3001acee646a07a222884387f1e56445d7852f7db92d40662e91101d5157dcd7ff517d3b864b557316b1dd21706fe16adb337ca7782ed5bb21e970afd9dc16eb36e08b728bba8608b15c30875fcbf6f939d96c7056edf024af12e1583758a005e6187cf7c2e2af1167700129ba74ef20e3afea22cab2ea9a24f90807cd839b884016c8b624d2cf13917cf427bee7548c51d4efbd1fc98b0034921c72645657350d189777cc3bec591fd205721d704de42442d2b8b742f12136af848ae0ed3150bb4987e31a3a544b9f79456a2fca7b149a8f1802781206b57d7ecbbd465c40a1b4a0e6f3a1f25c5ee35855908a46e4dec78dd586c086c04eba75769fdbc3cfae0cf2cd32abdcfe48e2b106b8df9a4b98291de33e648efe6f4355ee437ee7cdc854a3cd47c616eae431d6955cb78548ce93caec1547f2745e32686d930929982fa2bd1a187858511218c7342ad386105ea90887f0919d875685600706ab5bb683e1dc5196d8943ce821a639a7931e175df372b81901af3f08ef4bdcf10a18127efc074d190519a831e8ccaae06a84f641a2f5fab19fdc708e8d63fd66106acb2a720361f9f03a3756542d9a12d3ebb9301c121aa30f757ce4e56a2243cb882f9d7df7c26a52fc8ba8a0af2c1baf6746851a9c2a3e65ee15d456f9395482b5893c7937198415082992b7d7f34a547d77c68cdb77ed32ab1218d409bd71240857b13b0974d045e2c89ccf8e6a62104396e217f793a990d162d41ce4bee49792940496930a20724c9d4949eac997d9c2e5b9dfc47b04f0cb0b694e66f4e9cdc5b121893f79e52d3d61fca23e667da19286537fb2f3a3953947206806782d669ec03c17b1c7bbd09b4bff50d91252707a1a99d7cd1689bc4eba2f985524903b19d791da6fffaaa3d748918ac7653336924c960794bfc06f039580fc1ddad59980d1818c7ce79446f35576b7397caea996e359da3a3b3b7a882608ade4a9cf32380216633da5c5672cb0aed04512b6c784fb4b165ee2b878c502a4a3ce3c8fa48723694106166736b93b5e688961092f1ffbf603e815aab3faf971f9e3281f784ffa3a2dc23a164cdc4e81783d5486b4b6132ecd404744b248df1c32c769329f224674435237cfbb2f9806ccc1ba3c8961b4c34ef2ee69db7f469072a116f842b5399cea43402679db4245512a95107095eb057bb6ff24b6bc418b8c63d7bdac31c6802b29210d3662cd27d57386f1eafccbaf3837e2f8413f66239f2e689e537dc017d005ddcf003bc5c25e6e7b75b9af884e1b164717a14bd10633b4685b6d2ffbe03d5f5574b73daf7eba0a800f8b93af81850bc692b60913e16ae210b552ea00c4175c4514218ce4ca00fc16cc098c5c6aa499a2eda2b39cb80b80f39af8dbed96b9ea9b010990b6524e0133babae543296a6773577e1bea164689993cc2f4f14c63647c4bc9fb70091e09c85aa3d394f445567dfebfcbb2ba19dd37d4c0810cb929dc9ff9d2e5d5320439c7e568cfe1d4a1fec65ce576d9981ac8d45e5c21ee9eb43340b3db7d4de838730742616fb2d95dc2986960f08283207c414d907a044a3c96fe6a83beeb79ceeb9724ca40e2f0f340d8d2c6e64133d619594e73d592a9d24c5b00aa1dc8ce4752c2d86df0cc79e3d81a8a1b1d0cf50d47207d555be63db4f1d87e818082620474b0f8dfd7084941b14e8c99967d2af0552cbfe6cd388665ca8de290bd2593d44e139d24c69c1e09be1048da389f7b32828162ce85f830e4e2aa9f81eeb6e2f3e41fefffd2e611de17dd9f35062039c2b940b809560f9b3a749f0f60a04b06e024d107991ce612d2b0f9eed003b831476d71b7d1f07aa3aff90a353e778e920b519ca5b8ff394183b7cfe4f8fd4e73789cf600000000000000000000000000000000000000070b11171f24", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 57, - "comment": "signature that takes 43 iteration(s)", - "msg": "fe03000000000000000000000000000000000000000000000000000000000000", - "sig": "bbcda17759a78276b6332f3f95bbde79b676072fbd6fd60a4d43e25ce3cb2c34c4d81dc1a278a99c5d5faf8596b5ad4ff060294922ae3d220e5eae86212332da242a2e77c78db4e06a1d28220e3f4a100022a3b461d263c43d9bc5ce2e3984e192f3f8a5a2e1f25bf7a5e88dac482888fcb8657117a0911dde6c9cff20561460d7378821a073fe7eb2c6328f52c2c74f6448bedd9bee33c9b4bd28ad3410e3af07ce1f9770fae92d8996ea766e27c95fa5b8021c735413e86b277727f467f5786972c3df4e1547a2b921cb265f48a4a0e866eae0a44bbb32be8aca8cee6a6f9bb60069c3e8949a7d6c448f84e05cdd726bcb3224a50b49f6260e2482f45e047c3f49ac318a8ca1d9aa730c807f286303e837e6e8c33079ab12fa20433860caea7b91dc629feebb28ffda66e1e8636b1e4f90488a9dab533f0bd1596ac3d3708cfb2d30a08636e411fcaacd7aeff28d2253b128494d37878e9bef3676843352d01e266068081be7da3abef9603c7d17229e57714c61e512ed4e9b516d496bfd6a58d17be0910b280ef2e0684d94d957f80dfa1cf3a45c1b65f5a0dedd946b09f6d0f5e158f1dc931e4d44639a687924f8de96f1b061132224cead2c5fdde857e6848052c6ab47283db6095fc94b2c392dcdb741ff223febfd0a637f2162e862f4e9647c8f9dcba2e1be425f5308eb1bc507cd10af0df3a559d1e9d9fe91ed0f82b71585a16f8444e2908f166ef8af1152969a73efa663fca2aeed5273e17e84e694373d25265b0214f90a8f6b610e12f73af764183cab7e99f5adb7fef790ebb61574a424e2c40afda048ca5ee38d0e50f000c03aa3da579729f92b71f4e79e6fb386326863a2c48289224a22708e8cf3541467f0456ba6f2009c4937f88dfa15c0ffdbf4aac6d7f677544380b87284e142b71dc4ff51d385bc78752e6cd9cd7a12f54d6e38c7b7622527bae2ddc033ef88e313af84e18aa357c5ad56df9b1cb5ae393521f21ac8f912e5dbac2fd51aa7522ffb927f21b8e28d4bb9a3eb58a7b3e7b63027832d811ff57b1ce25583d2bc70aaf8cf91e6f8ece51433d97fe437127ad7f3b0647ae860d88f9e20dc6e281bac2e8f090911d7d390c6e8547240179871a55e0e73dd1114f0df5e380c56910fed56f674db18914eff380467d3fd01f3deee25bc525a672724d62f73fe7c0ff813c8a3202de503e38ba7c538219a56a44d5719685de991cc996f2b483fb8c0a2c818378ed02c4482ae0239fd494249151ccc433013dc544708b0fe45d98a6e0a6528b88c32892f64acd551a7d0b7bb884f3c7a18e58b8722e7a90b904d21d3004a00b468a5f06f4f141bac688d04f28bddb7f2421f0d2e4db7a9d7be94959dcadc9b1252b1d8547fb14cb81b089cf8c4d99ddac314519bb4c9a19eaa3018e805c642ea1362243caf68b8d4972bbd2f9dbd4f571fbddb00b65688ccdd344a47bf616adfa9b6927f796e08dad32605d97a90acfb70d4b4f9c95285541a820ca6e9e959bbbb1b77e2089f87fd41e824de384c3a59c251b7c571c1d89e40043307d170a4e679cad7ccede16cad15cbab0e56c4005f56fda088434eddb1b4eb04af6d7f8f5120b33fdc19858ece0cf755a57f3a2006750ba15d687a507d4e5215062ec3431f78f168218874bcb785262068e0daedbc750c1908420f87eca0f02fd304a52abb78c0968330a77e587a4e087a0baef408d3691290d2edc5387bfc169f52ade0b387f218dbb7efb9435d93a3a7876aee38e0a49c9c69d9a98197e092ae1faaf6c8ec41804b7da6e62210c4cc673952b95f55b929b1a8ea2b3d08dd5434c2651edc7a41dd031212538635cad974b382b670014a9241a1e2820b2a74998a46ed419900cc1464c2ffa33f4d20823efae2452aba5149e825ef1955572b6671f3ddb3452cfa1928e4e5fe84fe875ba853b3a56618be73b3c530ad3a6f8725883f7e23d136f64ff7cb727f1020b1f4a394719a71238e3d7542a66ac55011caa451a3a5e101c72be22fed87f9a663c5f0b0a4d711502391d1edbe0e90215b00fc08289b72425a0dac72546b539fb9cee77d3f084a39cb8071f504ef52979302836de1bc784b58dcaf8a3bb36981f45820a2cc35a29bb8a6857e7fae2e1632a857db40d1fc5bce39356d6c428cb5b4b8401aee5165be259031acb0af2a7433c41819a1c44e74a311707fc15ba6d4f0997873bc64358a5bb9fd4aa22b1caa9c030136e2b5f5b0a999e7ce009e3713dc032e4fea8f516a3e0ac277a36c29b5e2bf15cb4ff86110676ffcf33e4b7973a3bf248c7f6c02c9f091da8b85380684ff829bca245c3e3e53b67bfa4bcd34f0a598b5ef09bff00123ca0dad69518a765419fd72eff17602717957e3ee3df45a82a573319d6b40dd6beb7051966577d41383d97137eff7db84a2225e98d014f2111357edac272a89a7c50e0184b27d6a6ec611f70051100e9887657cecad1f34867e6d144c360e9eec53bff7b8a8a4ddd9cf254e5c74054bb8eec9359ca1fc91eaae77a9487685a209ea960b43a8cd198107b112deff2391cdc326300e35473a634c96d933009fd172601000c28fd58243469bc7a634c462b7f2147c99de6a6f03524f15fdc7db81357ebeb1eff404fc94f1c6e40912ce2661d8eb9d584f572a6152ff88d764c20ff024ff22f6f13605b3bd380d0e538f2b060ec6afca3fedc244e18f16a032eccf437f38b9db144770aa247e0fe7fe7001aedada4cee551e5e37a38b64e086e442799869b7948493526179807d628867bcc9fc6fff1a8d2a7203a5f0202e00fa2b7a851892bced0e5b2ef90501df3984f1a28746e6584fe944f6436daf003a6ef2613c20982e3ca9191228835ee1102e5fb67d5acf87e300a6de21d7091d6a573167b0a65f2dc79f979f5d1ce55dab07e2cb2567266f8e90ff619b6174110372f43baffe24e3711f114be914c0e01c56756e2460293281cdea5cf3321f789f64fc1f19269471f7373242c63563c7081e70fdf014ac4e11d1648e6eda56bf964599f7f91fa5b85f9c012236f700380a45b12985475ea38f03f1fa5453a782d059bdafa71344bbc2c60eec43d0edfab113d7f8761bf37adeee2ef88a5ab5060f004de5d69cbe2d772a627548a85618899a2f3d56ed971c8ce87acd78feb6476eebfc2f50075e984670a31d45d9a351886fb72cfd889c6c3486a824b0d6829d6db49812095873d9935843fd0433bdf9d4f4ebccfad9fb57fdb7f4bd73b0ceb1373b6e55d564f48f2d5d0036850ee0e04f824f45ccdcbb735dcfc5cd1f38c1238a28119008cfd6d608bc816d1222a01cf368f5871a9c25c3d6b023c235f8e2cc4e32bb365abdb16f5f9959236aeea856c562432129c1547b845ff4f143989e5d699003453bfa694577c9d5b9cbb21886ffd65b3b1d799ea31562264493d4f5f00b4531e132f7f608333382c23024936851e1c4e785f073a3441bca8823f8f56fe8ee7b484d09f98d898300f83974b9e39f56ca4184063901fd34837ae0269939d598131b93e68e982efc2e9f23183194d5b1bd977f886be2f58f7ce51a317adb1c29dc153316f7054cb17df75e455c1bdb3556e008a66954ee1c082e23203d89d8ede425dc355c592681fb20b8dc5d9ba8563da39470c3a86eff22c218f796f9594a0cdd39b7e12d2ebc46e30650756f656241606a62875b89f864c9bb7ec6f22a3086377146a053b373e5e6016a690c5eaca8c923d17e7d49cd2e81a8c2b41fe008b742983b48b973a2e87a03295868dd6ec34ea1cf51c359d5ddc8a0f3b480b443f9aa05ff0b98da9bb79595708b9ccb683e4580d20b933b19dc025f7e8037ca6fa70260a0ce40e354b73304b0840121892d408a19ede4eeaa311166d27e711deb9e4c2f22486d01db58a504caede74e928ce2c39e68fda561cc748cd20dd5930241eb700a177fea79a33f041c72bb5ade325eaa2f7ae60d9a9c65c314ed410a94299f608a9fd3be24f427f682bb27fb32f9bab81dcb492605779267ee0b7195ca1b7c52103692f204fd4cb665f279fb3a4a392022b8736bf5af8480bc5f766834a8e1944c83f41185d2704b6938a5d9d03263e3deae764d5e9882b7b2e4521b379d870d4968eec4099cf9007e6519809ff133b36eb2f728159b36934834990096418c1620dc41e53f3eb8a55c6657687a1db8e5756c2a8250d8ac9d08e5487ff27d75b8efe3351318dd23b791e580f09feb7b13f4d82fb0667fa66c32f6074bddb6843cccb7a6cc7769822dcc0ab6487f54c49d61f2109b47cb2c87c0f6f158298fd22f1b9fa39ce57c1ec04b69f4ca155f8ef86d321fc3bfd52d26b58f9c108c729fa5b5bb3426628610ba05e816f362815b685a14aab96b63cf2ee717aa975ed4d3cc7172e17d97eab68a8e32220a59279e543b2f4894fdcdb792a7da257dd004eea12cac243c7b9b67b0b035b5d9bf5dd54d7e1fcb0a44c7a18cf45c765777c3fdf20bb4fb29adccd24952047234331feb580651282e1a523e96e0d6bc35a50cb42ace95edb1eb7bbdb91e499d3cfb463b61ee61f851bfff32c944f8b1090e7e3fd8d02f05740a840fd6b04e969ea2b6c3f9fb7086267ba3bbdfe3ee414994c30622254253829aa2a5c6d4060c35444e7f8288a5b2b6d6eef8fafc0000000000000000070910141f2f", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 58, - "comment": "signature that takes 44 iteration(s)", - "msg": "bc10000000000000000000000000000000000000000000000000000000000000", - "sig": "7886b408e355ac8eed58a28db36fbcbd60e3c9fca1f77e88ab399acdf57fd12c03fed5333307614b530ea3446cfdaac07ce1fd5310cca41e224bba5c0387aaf0091a1ff0727cb4f62bde0cc681d1ff59294df794196d69a377bf46fcd717c44904184f0b697713bfecc4ebed5e119f23deed3de861965ce6c8c7573e45f29f819c5a67f858edd3a223ab300fe97f3a019a9ec43f24058ff10241ffd008164c78acadbe329340da4a98b07ad384d87a9dcb82dc30f341f699e1d6865c00ce0d33533f52f6a3186add7d5c56555ecc7a4198550103c46a60e9987e00588c8720f4bafdc8f52c76785bd7c7ae66954b1f89a3372df91d963cacfccfa384c9dd1f00a381dc16fe205391c60ccc9997f50a05d7ec28a41921001228450ba221c9887c04f6c127a4b979e595d9d48734147d261587144a702ef180e845733abfca6b60c628e2cdfbfe9dc9e5c310cc4a9a79e9fff5c61af2e9b8eb25df72fac662f3b0c4860f5cb30ad2510013428c18cf2fac4fe524a86d600460d73bbdd287e470bc2c3e92df0c132dfde71447583dbb0472c2f6c6b99835d351788ddd09d2209191ba821fdaf237851d2d8698ebdae44709ba44358a49924ed5df96755b30fe5bd467714860e92d5c68c22eff2da7024d53fbffb6f04dfda5e9efd44b529fd708dd6898311e5a9bd73d2acc5518afb2341144fdd63159a2d8c092cbffafe65e43fd29b0e6a3183ba3eb0f4a0f393d4b096a195aae986861e7ec97a70d5553941e23bc96b10ef09397bd938f47d32c6a4efcbdb45c75214ad4f43d1dd73bb4a929b25e5c7fd00b55d16a0fbd2b4cfecd03ba0d94feb86837d404f03a296514cdfaa9dbf424b9c3344a84f2a99efa4d273701c32780a8a0bc568959dec3cb58ad52010253eb1096f752fb3eaf9edd4269cd53195478d6d9ac8229aff4efa1a7b7b924b38d9d5babdb6efd62029d21227e5c49fe344980a900d395a5635d5a5d5e4e60df03e587e5a69e0ae1114d9128e8162d111753456e0e0e9266587873f81ad81c3121eaa4f1937d5b2f3a36680002e81cad221678122a456f0304b36bdadf95de811143b1daaf48df48db876dfece80e7a02590a597d30cb02f43fd0ed854806d8e586785c01633b5e1aff69fccac11eb74dd4d15d4c7785d0e8de88163c8e05c07b2dcbe2ae0a6001e4b696751ee80393036d8d2f825d88ef3d7ce51cb2d24870eaef40d3ef91293457319151efc02403b5ced3ba2cf0eb4c825230e8a8e89f31016ca19d5cf3cd20d2d5b44d9748afaa034f8222d5cf20183783a26728df676ff8f55caa3f17df71149d1d4e9f71d058a3d1d6c2d4e4d2030d31c795c2fcf08832a4a8d1c2b2297ea3081a1b6c5c74e297b576a3b3901b071c6cfedf84e619e7c879034c36c0759282a271dc4c1444c6603fa2225aab788a5ae11aa242ce8dbd3422d4274dfc807812fa1c7d119a6d43a9e35d4af818b3727d165813d65441d2d8b42bde43d56d781f5b9b341bfcac73180d88c933d9e25c9a64cfcf07f3e03f89797156630f953e8380859f37c6c630fb4a95b290fcbd85b9f2e05778aa874a4936e10638d21fe3cfe0176191399ed293cc6230451a163dcc2a525ef130a8d1c2ad93ee87682ba8e061101bcc332794c6ee2673ab298982318a3b68d10dfc46e5ecfda4e1164b35dbd296e4bec9a01df32704b76315ac1c5c660b871f5d0ccf4065d8de4c1ffcc8dee4178bbab66f1b02179e6f73bf19822ca9fb284021afe756259f051c11694814b8b019bdaa9fb261e8dedcafd2d69b19d1f96f1bc82ec77ef51031b96dc65481885763c5e6746ff0bca40d1c375be2b2d4cde654cca8415cb2a83a66d216001d692c4937c138e6e3b1c18c54c02042f8d58033fd49936308d1377e5d88b98b4429afaf5e4af68f4a1f5b2e039cd6b5dd3d04777e65c1b2abaebc20549251188f697d1c7373a62cb7b08d2dd367021bce2b5f4a28e6e93d61733eda231de2b35c9e2c84b8063e9128671a9a27b21ce5b2c6196769c0837fc1f815439bec0536f017f10803f5ca14f1280988679d604e19330f625e3965e66d59bd820cc15a3ff8f28692381e2477453d153f5e139855e6ede385b5b7d72506a3bf53ac3ee843a8dadaa8dab1e2f84fdea598e2c6aa4e3b4ffc58a78b53171952d7d49b05fb6e59ed5ec857747f9b1526a256fc0f048c0c2e239ef8dbdaaf671eb75c56309f56397a3515ef8b696128c08cad511fbc86492e55feecc19a4c854c40d36cf7215d3980b7243107caf3a3d7ef580f2db196e1424d35dbeff8277d8c0b0e749e26735b78e10db19c8274a81b1168f09504d0a2aa90213a72bbb6881064db6b488c8c4bb5620b8c2793e853660adca017e12815b378106a88e59505be0eeb43b03afc211103f2d20174e5ef5772b9e87953f9ba96ca1e69bf79939d6eb75833dfb233d2f7fffe6cd1212ad896105492ee863883382403d0e32124e8a5fb30dd3d5a44c5859c2f7a1ecb017410fc7208145193230273e306622c8cff46393a73807cb210ff8c8e9bdbbf474377758214b4bcf6d2d45ffbc3b7664cb4c7f4d9dfe2fd8d76a2f9a09922d6f5876a09fa45617ce12e0bf0ecac9ccb6041568c0e1da7b023ff02542caca8198844eaee7144d535583bc7628c11b3c02d285ba06445cfc96149af917ff7b23a3a57aa9593d458d10e48c380396debf3d00dad69c5e234ef2dd8f27bde03bb8a214b8d8500e5688e5eb75ff30d6e0ca650b283d726096a46376fcb77a9ebfeec2a1a796193111f491e7c25e4a817aaa8333d4485a73f6646ff228985080376264e290cdeb8abb5e52b5003b6bdad5e941012edc370533c1773e8182f019c140595cc28ee1308c6eca317eeeabf6b8c630274327ce81da763cb7adcc4a625f0c2252d3fa2e2a75cee7d1b457f74760accb952e364e68b300e509ad72b06f64925a410c5ad29a55433b926d1cd6fa754587e1c761035c86f1b0130acf97a82a89b7a9a16981d8c451ef529dfeb7a8b072089fda297efc6f795fe4e91c49a00a5388d19bd553d0dd2db09bb53aaec2f2b1db95d5f3ed9b470d8e8ca43c83e04aae5865f84f590b58e7fb9c86b665bcac31841c31b965622e40f5d2f01bacbd2cfc9a97645bb303968c2bc041074fb9f80ffb6f7c4ae869942a1b8537c5bceac69010991cbfa28eef201b6f31bdeb3acaefc6a5fea55f8aed6ce9160973d621879ccc6d3c96921bbe4e3febc7e9308f0cab473874812051043011b4c1d73476592a5fef111e6e858b88fff4c03b99fb22b49817a7153c2251f4524ebab30968cbc0317cffd227183c3fabc5281df4467cac43f17d1ddc40047d1ae3935e354334ac595f0b756a8d9d712717f7ed6d83c0a58364ac96b294f17a411731b4d46535e20995af972cf729f7a8c222237e4aeb7cf8694d7432c95c7e9125bb03b0da402a24dca423eb97433685e698be8d0555292a3af58a36c5f23ba1cce6854e5cba1bb1d6c989ad55dab142ffaf46a1ce65d73994132962c6c50868bc697b2848f6b9f78ea71ccd9122cb6686775d7f39d3245ed1fef51ab2b9d6c95201169c1200021a315aebf2501460859b32feed4e37709c1d3fd82c495c69981043ae54ba577276e46e155f568b7efa9db1cb204a6b601e4562535ff4edcd884a2ec25d96286f560652c5ac73f12933d9137016f4fc3dc0ced8957523109cc0f97ab47d4d29d577c2618e88c4a4b6302cf01242a6af14aa1bfa3a287a3887885b8d0d276f3b113b1cd601f6e78e5b0a4aa1bdd15a5dac01213f57fac75bd292693bef59a3c1dba65d235c6834568f9a25e0a9c8150199f378ae482ada1adc67af79177d7e8d2c08e743264299bd2e92803256c8f7da050c4b8e097b5b8edfdab9c3d6fc8f6b2077d99f914d6fa20c10b65391be16b6bc0ad69794ee5e6c68b722765b12542ec9d93e6f622eac5a75551c0826f95c69a50e6ba8e7b255e002a6e8db7233cafdff1c0e3106b7126bff22c577874a861d86a1b323eb3936a4cc429e85023984f7940db34bebf39ba32e6242bdd78a9e707ed14e874dd9b93e76cb258b19a129a4b7368e424a56224187a3155349060e8bd0c0f71fe47a003314313a5bc93e774eec2def8a26f48ee2c84860b08e3cd414054792e2cda188d14a7a13ec99dd4641b5ee12592b312192f20ab577b1df34c445ea1d656c9c7ab466344bfbd4be5a4b548bd201031eb3bb49ab4b9c81a76022c413d62836ad9d5355f6b69b9215f9e729e8dd5cb9d9db4b2cda30928886ddb9ff89b48c49c4490abf9dbbd75aa0db55409ee084ecf6c0b604fcb6691e3fd8f54aece7c783e4c623920d52b5aa79ccb6e0335ae1c215c2198c0e65d0399621896009a21b824686114d958bf5211a4c51d0890a376335e50442cea9241ae3f6c50f3cb53088aedb6658254210acc27796bbd7ecde4d12f80db93971907fa13fefa7203e566c63a121a3bbe61c486cb044bd94b8f14d172469160984e5cbf0577d581d4500a9b1a94403de6f9dfcf7c65ecc9f92acc734cc6c0c59c6df459e383b73c265f337a83b0bddc1b0a494a0e67c7fa2455766779ac3080910162627c1101f3d4a545769d6e36fbdd8ecf075c6d9fb300000000000000000000000000000000000000000000000060d161b1f20", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 59, - "comment": "sample_in_ball requires 1 SHAKE blocks", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "0d0d1a7af2d4eff6d4af7435a634d28ec5d23595fe7a72cf76d30f1fe16620c64862e4aad54fb78f8ea752b1e43e4e5884d7226840beb36a76f6a9b1b7d50b0faf7b8463f57c66240e06a22f5f3de4fe35c1bc6b5e42ecb1c0758069223e02f42efdbbbfbc87b4c0736141a70e6dee41bed27fcfdcb94f4213a0f99a02beba309a93d343cc932a6fd67fb90d6de7a81101a678e6d47d8b1c8bd67fe386dca360be789555196e2ff8704c175ab60a8bf3c9f3bbae1ee5a128f67467d21fe8a62e5f8ad8127b8d7eb37e43abc963521e79d0f1ed57fa341f743246fe69d97afc9a13824c79f7f3dedd286f3de739158a0900c99d9c8e5603df109c25d993f634582c832a79c7bd8cbf3ba07fc4d9e9ca8c1157434515538285417e6424209173c6dafe54c37e4424de0f25454b1713fdc3e72d01a2acbeab4d7f60d17dcd073c60b0ad5252cfa137c138448c931498f61fdf8f449225b07e7e0fafafb1f274fe5cbaaa136e62362877f643c7c94946075e8928ec47c04ae54d2085f7f2b1ef0e46dfb31b9a19135b6cc9da876dace6f61c2766b463b24c0aac5068714e348dea399986c4e8b8bdb16768e7ab81e9ea13e435f97e35d268bb679071d5b99d0d2f1526833e8624b6e4ff1ba3f5af2b23bce93dc7c2c4370cfbe698a3297005c9fde7af66bce7c9ef68337b04d7681e303a824e00acdae2ee3eb8c3e7507e46d67a4cfcfa9473bfa6334f2170911bf2ea75a3618cac939d11d6a778101e033cad958aecd89feabfa19dc6dc73584917834ed6552966f7bec4546ab24c643db25722b3ba412de04e9195898388d9ce04cdd9343da69ac9b3d3155620dde4052e9e30529904f25dd6233bafd4493b66844c8fa5d831377dc3ff8829114000799801d46586dc2d2059f6bcaa43b899e089b4f3a5ed4e6a7f1df5b8d42fda456a70e10b2ae14630f27e4c7257f5df23ad032c1edde44073585c04c1231e085591771cb64aaf62febedb33df56bc62f4d126cf8be4332ce4965e6e67d0be7871d81dab963c576ad7123bbff510f282bf66c0c1ea04aaa05a7a4d410d0e7b6ed22025dcb6ceac78f377306e973973adcee776ecacaa560dc8008799b306d5e617b2f51159b1e5fe5daf40f8f488f077cc55bbefbe8f5a61c28ae2b1493272dc6a4e34854f73f74c3442d9c302f96b6e721e2956ee0bcdb9999ff36d74b8d4ef036afbdaea5f977da2b94d0aa9136abd6dc26348873090cfe3d4bdda4d962f9382576bbccf8ba227af4ca8e017f65b469d2e3d35132fac40cdf03bf8f6beee66fe9214e1bf684e0aae75e4141d9daa1c77ef409f56424b01acc7ffda11cb9bf64a9aa71b484b49b9ee82dd8178dd4adc91d8d176f83d2cc7516d2195917fc246ebdc0dba4cb5a54ac6169bacbcd79adb72d593fcc3fa289f1e4bffb4612ba7a3318e607b0b27733cc70a2e2b4099056731ecda3212d1719a6902cdd6a05bd70d389da1dd0d0b4f6c4968676fe33c6e32d791c85b16cc9f4289bdd09acadd9f902d9a91f1559bd40eb6b73da7a623048140f73454e4ccb4ad65038109f6eba9fa01b0a3fe1af228e2c4134be136db2b029879e101aa8ab264e554818450734eb5a900497d906e20d36eb3848b092c778054c5ecee767c00185ddea39160e4513be858bfe5c7c7febf97ee8e2b2fb477bfb10c11f3b756c0da1d87e3121ab4454016b36fcd8f6d2633c73d4528221974b3f21ed3d464d47bacaadbb4647320bf0bcde38b0a75b6c3aac8b72d3c2c179417d05858ae4bd72d9c16713f7c116dda3ff8164710d4d14964b33b00b268007f8cde2eacea5108fed77d7bff70273f351b4e160d28d02576dd5f3fc3ab264c5927cddb6f9a81b852d24842bd5db5c5f2d893b2f013fc75426ef2414bad1b845ba7833c88a8ce76fe2644455be2ac1b9d1e31791693fd65f1ce35fee9d17b42b444bf1277f2646a19d76952b3fa3846c3d258f9a1835a709fc21472b0f7de7a729111e850f27f88764b3ab4baaeb6cfc644b9b6a552a61a7286b5af8011ede05845cb9359232f02ad8b3605b00cbbd83069f26b610378055c004a456c7c44606125b7b076b3f955117e03eaa514da82a9650e8b9247902c5048ff776ecaaa5ea57df61d726ff1754d4b1393933599edc49617836ecf78cc7dd45750b666b73150496e3999e339243f5644d5a3e57c6cdef2ea6c967f8bc93c27aa56ba5352666ab6dbccec415f610bcc76879793935df8e594f5c6b80dc0adcea1a1d5854f447604c54dad61cf0ac91d27ef963e6889075163e89cdec0aebf32080efcc58280b705a029511f21d311c1644623f82039e096f7e1d2518928847abd479840b65cf10d15851976e47444d64c6d4425310a3b5efe9b584ce7aa01b1f79d6e3092486f91fe75288736e852c0132561a7616f21b7713ec53f0dc53432f53eb4ad778dbe14664b55553ba342eaf94e9f76320f8f658b4c5173ab938fbbfe20c9987318c1a5104efe41419926218d30b0c97a366e60f6d1240e7f601a1b119df36cda11bdf7fb531a27979c9823efd2a75c70387f0296dc7382f570fe59568afb406a48e7c13bcb40204c92cfe13b3980410b229767a5412a7db82845da135cb6d5b2f9f5b22518b2115dfb02115fa1c4c3177a55f5c194450f0f0a518df7755b0b12eb412f5f6ee2256bb95d2985bdf1257769718de9b4f4281c3eb3407f175c0b43fee6b94b00875dca0983ae763624bc4e84e9a78f778dedef5eb078ee87a34941005c15cf42ee05cafe098005b1770ccce4e59d9d3f6eab9fb2673766d9b70ac11cd6d8b9d00809e58a046d95ff62e78a8e5525af54094c907019ec661600ec2c4ce5337371a1daad0e37f3a5cdd96a3d985456a588b5c1f61f36a33c6444c3b67c445bf95e9035cd4f77191a95a7e4c20715e55dbe43196809123499148a930321e7b2cc7809cf517fc4b2b0b49e57cde4b6aae620fe8cd0b38358685ab80061c1c126a1f3a96ab34fa957236cc6c59ed962b3bb006a1c122da796bf6bcf7dbeb64f4339c63d3a437b5898be19f6ce62024cf9b9c89964569f176fb697430e553a7c0936056183223fdab2f910047ad5e64098a44a2edbfd3007b0b5e4a5d1e6ecb44f137dae2dfc45e96f03e75c900f3f84e2653efded35a3c8b27e310dc361c0740524e52a1bbecce57d59c4913313e62bbb63c95a93512bf09228918bbf921cd5c62b8914b7142d6abf8d632c3ac44ebb6936c638d56cfaa7cee463838a921398acbbcb44bce621bfd81fab34a8ec33810eeb89fbc3cc469990089d2291e1e873b31398f2799b8d62d429b998422ed634bd7a6de8e991ba8492c001fc5df8b0014fda377cbc5ac74e40d50773ab5c2b4d08dfbf3cca590a77f4db0380fe7af822207aaf99c38676327ccd9aad50b2d4db5aedf74b1cdc50c484d455429352ef0aacedcd9792dc26c66081c28ecabc445b6f1f547a24403e18b0468c8881bdc3e82f7bcce254944271c3ba06c80555c8f3d2d051fb6007507eadf8fb991f45c0c9e9ff08838a425a96d72fc20d642c2eef45b4fa43e7b380d8b6648695c0b9440cc66665435ffd3df10fd786f7638e13706f6c5651dfe5f125158ff3d1da84cad23129e11d79d0f95548318b1c794990174daa895e4b984c175136185be534ed6bff9231c215fbf6bd297e24f528cda523d62b44aec15fdfb36281d804625db07567fdb06779325987f69f16f19df737d5f65d1abadfae70a1a4daba5a87e4ea3a09751ece2ec21dd24f719b1f57e795819689c8f2e83beff593735825a1ff8e4e4df9d031dd66120dcba07e6bfbf1b0946b3585a5eb807c1632a75353e8f7b8c4f8ff0af978afe2bec80d3b94917773564d7efd92a79cad26360b599be49bc657b132b25f459d58166110fa626cf1731be419105b4bd235176d60efa939fdd8dc213c695674bca27f161da4514f646f33557aca06189698f2953674ee73be89e3fc4c014877c6bec370ca1fe446686200a94ded3382c4f4bc58cdc12c354a486463959cb91c2ea0ae965f912364c5d98acd40ee312178b479b540875fb2a0164b7134564bf7fabf59add993b08a904452152031a784cbd36e19a47d4c9371e7774d3433fecb5d072d059b01ebd3279ceeba80b356e3628874008d801ed74717c70a93411603f1faa3924414665a95c475ac42de8d616de8be5c00fb90e5ad13079e54d1c7000905b62742ed70555ec406b49cd4aa6ea68342aa7763530b180e4f790475eefe1094426b7de9e0163a4990ea3494909c6c6de6b7462d70c8f2dca3152d81c93a8c184b0c54da7fb604f835df34506731774e6b8f2361586ccc17f35c8e21795ccb68a5cd73355c98a17c9ae35ed22f6c0a36c4da30af96ce7347375144a80dd851fda4971f20e9d6d18878d74803b577af4fa8f34c05b380acbc5282eb63f9345e4dc1f9f0cf8808a204ec789ed31ac9f009790d5c9b7d744ee3b29d911014c12b53ff691fce0ae5d53dfe1c7a367e694fcd2f688d46758ec308f3f9736701dd825153df883c0dc539c9dc3dc7dc9a9a35f453c306fc57faf76451bef45889e4ab0a4a6dbd377996c7cf80e0e7192234475d93f3f813197ea2d3fb112c2e97cceef2000000000000000000000000000000000000000000000003080b131920", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 60, - "comment": "sample_in_ball requires 76 SHAKE bytes", - "msg": "9e17000000000000000000000000000000000000000000000000000000000000", - "sig": "c900c9555fef3710097fa1a132c5d61623c554c4c837d185b7f3d1671a8926062e094cd3680be899883c036db34e39698133f314f6148dc3aafa088c06dc01009685f1a0ddca3b0311f9f521154c8a692a165c3a488419c4745412cb06392dc6a4d12286627b6eaba2f376a3225ea85f5890df2d03ef9a565ab2f94c99c25d9239bff7ac74e94df677e7282c0dd44c06fc2f26b33cfbf8da05b50fe725ae9de58d6be87628dc41ca774c8ce106428f012f2a806631cb5c763c722e04fc7e44f86fc75b1398a54412af3730a3c60e47d611530b873feba32ba4b34081e02652bc006b9e106ad6ff4b698445e0f0514837f94e4c49f52f42b6d1b655f90254adb8456e903224fc60271f280360a632afb017b5255b6923eb8c8cbfd62d24643e8f100391fd713b27fb7e8adcef58c26ac4953c3a73bb6d12262f78228774e274283f8b810c317d9ec0eafc05c6dfcac42d6bef8f8963d17667f7029182dce0566041612a7c9e6a5a9bfd953caa1e88287a20a83985ee07eae3c5c8aa408667556f7e19d657fe11036a227342358b7e42d5015513ad8ec587a5f19b33ec2e06a146904edb381ab11b1c0b0cada40d89cbcf5d7c9f4e15d8d7cca01ead1a66281d8e5f64ddc1393c2a1270d4a97b405d4d21adb189b8eb44098902eb48b50c5f5d1496bf5d5ed0f74e58b8aceab89a7cfbfff608a8a90d2baacd652115596e72fa1740848b2cb6b5bd8ecee89aec60118f16f4706edc781c6225daa0bc8539d82addbcb8810ce2687f1a171a3aee07516cfd6697c2e5d63629bc43ea3ed4a982bd516f3f448a50dabd95ac314c92f92d468f4f063b1fff69dcbdc3a4d8d21c01deeaaef7b9be41e934a68c144643a99ccceb8e3106ca28e7b0bfb3a9c5e31e33a822573db60e4a520e8f2190361b3387ca038c0210fadfd294bf8c1b302657211a54ff4b159be164680d3eb4c9abc7d6b07c2b81a5085f4759465f95f367005fa33544d56458c2b51bbab862135745a22d994e30692ca39b8fdba968b3766bb627dd6463c54487b81a27cdf9b1daab2a83c6af174f96dc454feea043bc0cca7ff9cffbe6e1ac04ec830a0b4e5d698681c9ce860da61249f3137e7980bde1cd4eb0a545c10f725f26a9e0d4e59987c4d516c28e938290bd88ec1729a553f6c7e52ce9fcc402fffdf1aaf47def0875c8afcb8167a530a94291cf107e095f90d92998f4200fbde7e5ebdb8a3c9282f57c2efe94ccec3b5aaae61afcb7892f0b20c3878e95b53a70f21f327b70555550a4805ac6a706d4bc408f73016b1045e2fe2c2be0195af8c44855e3233f99d5aad848cca7fcc43a0b5a0b37f54fd8d9f24c365011448a85f7fba7a9a7b4aec183bb680198d1626e24948027081d8e91aa6cce10cea8a6314eec2c74787cbb627a09f4ba7a691d963c8c026a2c1abd6a14059ff57493e5bf14c18fe982f7921262c85f80ba72f4dd88eda886ac13e63a8bdd9f72b04a781ea9e4ee2f58a15acbeb2a693a8f61091c02aa0932154817aaaebdcb7471b9d0b4aee6dc34f2ca644b0114b6244579f77e096e121e7143b77443459bd5cd1ddd9623fc5784bf34267bcd78068a0b2225f21ad1935ae44bcfd1a23ab4d012c8ffc9276d4e0abb5f100b6a90ccd7ffc73a44b5169a027b2f92f7a49573c997554e94fd5a4bf54f4cc473e794b60cb3a0b0c5ccfe6263c4f91d77def6ca8c0fbf91e923234c8a2657d91f6ed08e6ee04b3b2a62f29b5f467168d580848912b5c2c05386aa52ff2999d6f7d5b142cb1bb78a70db30d4bdc850d52e0febcbe452966f5a5d6f5fbd28aa498497ab03da0b3b773bb2849a4f1d6ce50ed0d356c3142d33eda4f07907c6205b52cc66d49a5eab02d8fedd50847456702f74466bc54d9d12841e65c0594bf55539c177cae24e9572b1adb5b26310ed4ddc2a14421bcc142ffb3a43acd612df758abfd95042fccd186d3d9c5b0cee0857f37231bc9f8fd80d4db3259465ef11d0679210394713d99bda76d6ccda91d31a287ad749a344050a9ed08f01be70350cc2991dd4dccc04ff78b9c9d339d097ae2d828afb843418c82a707c0eccaf9a3b412fc68d5725a31a064112930a8c6c7350664604606d4d1f817c842ee4ff032f69ecaa0cbd49768d13d06835a07ac388da3bef18115fb096ec01d42966d84795551b9ca8e0d11734161c71713de45b545695b14cf2d883e4cd8524e9da3f26f390dff3a23b605e24e812c561af01ff087c544af8e1b4aadcb4ff5cab5ec1d064cb9d340a8b0273f178bdc8b413ac88cd274b7f0c1bb67f758682e31376632e6cc2cc4c16705eab7b1fdc1127ce985c0caca5818f661994c7a6cede3ba865488811e0cd226def609c0a857cd2fea55daf0e116d18d0d1ab393403ea1393fe4736ecd5f0d31adf6f43eb6be97cf58f8e5bf5b54cd2ac0d2a444e8f5088396fbd587048de2fd1ce1f3dc69e1601d0f723b843cce8cd9e6144562003e5bd448510a3d385aa231c12432ecfcbd58279778b93019f03e78ad39883dbc1907d939c1dbbf5f21a76ded80efce94867de48fb54e64aa0cb93b2931fcbb7cdc45bedee33e1552c624d19b116dacbf4bc874274bb242cf3ed50489d7dda672833f26d7978fc0766c44ee270dc4c70f16705ce3af7eb4d9acd2d135dbbb3cbd8ece1db7aba3e783c853f1b25a30c04fdce0d8382b60df232b3e94d976b66b356827d55046a317dd6ebe6029472dd2733d960dc4b6fd1610d4ce57e45c48ceb482b8af3ff722ec97c9e569fc066edff9be4df60f66e862c06a6e04d7401bb2b7156f8b85747e9c51510d5cc6e0ea37bbef7f8d8124fc857258e91f9e1c182eeff2c4644fa079527721e846ef62bb01ac56d61ce40a2b3ebe75c0b19e716b40a83933e9d4a8a3f31c7245a5cf049be097e7a70921b850978f9f4205d58a9e0360d8421060bf32eb6b46ab7e3378e9c28657c42b14a94e2b658d2f5d3cc3a5e13f50d929204fb4d66230d2075831646fb3775d7dd99755df394c81ef115cbac093c69c735cc07f8917732dfd564d13454f617826b23849a73191b7af7992320ed5ae41b89ec7fd62a3e42bc48dc987ac55f8e552d0e056343b80981c9c2f2fd2d05ea3c8b7be5bb115a686ea99917e8569160a0fac13b7602d46f29190c6f80f69e46c519619d8178b7f79ee1bd6f87afd5beac38a3842f734bcdf6014052ed8769af35ff8a329b50942d1c99134fc0c31bf5a57a26367c0e7d599e5385dbb328d64557d6034122fb8bee15ed62d8de367a1be38f0c62777fd1f27438fabc01b186cc4c045c4c9aca26b64fa1e41bafcf859bd650836826c45622892ff9605b61cdd8ddbf59a4a1bbaaf8f9cda01545f25957c2636668c8e9c2c88dbc129d2633b6dd8152831996bdffc019fefbbb0178a524e4b0e69e1c477bb9007d679725f1ea440fd94ddf2ede8b6f909ff6de1b45603ecf44e63a64d0149599cf49b60db5e21af00b3aa99afa349e96a57cea5763a096d97c17b7cfd6148fdc89470b1873ca1bbaf004eeb665159d57a7a0dd330e560caae5ccf348818984dd5b94ff8d78931624e771f22f0cc18fa54a5068fd9c8123218c4bbd8e8996f128ae39a10118840c63a5d8819d550aef6a11252cdaa0a39936de328c12c5fea5e7f2013b812510e8a75492b5f694f90682dd8176d4fed45b3919ae39f90c2bdc568392c139f85a84940b5e0ea2a79a7b28ac3d5a79e32e545f7b9de9d6994a6fda228030f74288e967d9b60c51fcf047af3b4a86a5163849bec0d2b63b2f89ec5c6f8784341818d2196a7e8c98881aeca2869088e7de9afed497e4535894022eb36fad950e396dd1befe453b14e968b6bd9f810393193e90774eb4131b6ae211641b15f13ed5482b5fc29e68f91046b1a895c3a9464d1e699a30abb85afbe40af3e33a1dc7e95f93294b3712ca8eac40326a32a7f6470f10ec9888708be86c90122df4e3a8da7778ca05a187539064ddf9908d7b6a82d1ff8905dccff610c9765953cd67e3fb4ccfddfe3009fb6f2674bd99228ee3613715897a35849a86bc0a38416540de2b5343c15b1d70d2a73da969ef67d25484bbdb2d9fa7031930065d4487ea212f9fcf7fe9b044d90572f98add754b8f13757651f065b43325eb0cc6a6b72381347f8d56b99876b0cbbd936bb2ac401effb14a5e828a2d74d12fa8aeeed3c64fd15868903920fbd0a4134f24f3f1cea1122c7cf9a5905b70c2162d9436c456d240d509169a67c899b0256d9304c064682a986272d12b9b4562ea4dd581e468b65653d290bbbe6fb42c79f26e2a12792ba8c18bf59f6fab262c2fdcc5e1679b45e8e5e400683b8bce46d4aa7401daa837fbc0f2834d84225fd82f3d35e10f505ddc776a960e3387af22681d85e6a5f3a0318fb133ffddd7603183dbfa4d36fd66e8bb2adbbbd72ccc3f003b0af15f1a03893439b3953670c1a5a9a67aaec332db413c55896f9ad05691ac236ad7a01338152972add9c221a681b7350bb00d365b5b88d04923d118d547ba7bfc74d80e4a54b3b23a9b09c79e9b368ef10d9e7baca7249beeaf1df2a3de73d79a670ebb4d6d708397efff2f303d44464c920631a6bbbec2dadf1321303845585da3b5ea063d436869aaf3fb00000000000000000000000000000006070e162028", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 61, - "comment": "z_max below the limit", - "msg": "8700000000000000000000000000000000000000000000000000000000000000", - "sig": "0d671077c3e64cd312a5554e0d6728bb10120a34b3de9a7d85ce41ea84fc1e02695340f707cbdb4dcfb3d6f590978c29426c111719a47a90d0223edb934a716d7dea3804153a75c60d56d0bd4334e2d7ec9bb9db4393eaa9a98b1bc37d9b90df162945841c4815b17fe28090b7305d2e61c3ca0d6f2d7a6e39c60378f043494d541e7f47d70a6813daee881ddc46e8244df4732c82b2d32ce01c0edb0a19a31e63516f0da13228ab4e2aefd5b9d069329af236a971cbf554713cc6484ed052e7826388f5f0a1fd8b2bd1b92421edef80478f457c899edbd251d5efbb77eaa4549f2d923d7fa5ddfc3b559af16a8f690223180ad08fef97e992d5d0e44af54714484359ce1a891bdb019de9ef87b1cc626d0c9a09a2949f15095850e997d42e45774e5ba9bc56bd6e6d19be2ca567b534c155905deec8dba9423469fd25cc807f079dc7bf2be38a350904c4ee3f4d271c90e323fde28b66f91dd47ca7aa74cc3faa9a5f1d314189985b135aa7e6aae41d23a162a8af8e51709b54265b51d9527fcea0c86226cfae391a4b0e18634deae056e8e34ad7902f48b099242e4663e2dbccb9c145dfe0d780590451ee139195ee493c7104792b63260291da3957f1fbfd2e8af9774c22bf224d547b1565759e2437fe48f5a976c2f273316acc789e3ad247266048d19172a16972599f50d4021afbbdc6e4b6f03ab79e5fd4e550f8419b9b2a8ce174c521d48959f83ccb15d8dd55a64b12d5c8d6037382c3a232c89a8b56318f1553c9844b81905d1e00c46733f24a6d5f88b67c0245e206797c1bebd61576b20b179c2ee7092a978a710c74fa32fd648ffb7ddde487309f14866d3466922dbdd6228316519cf1338a0e544de4266fd4d9507216913dd554c4603e74d2b5f8e4f2114059f24bdd3ca44a88d88007fc45d571767616aa45bafd6ef4977bf8459099ad4434b8a214207289bbf59438d0760bc46d555acbf6595a5e5e9ebeb9e175d0b6c3e4b37a99d1e5ab0c07cdfe8145344c9e44fa1ca5d77f28db5246953e4542eaa186ceb249ff12c15f6e59b1b22ad003c974ca59c29e87034d5fce8dd5e03a55bc2c3dc22f3298ba4a0e2c3f85857fbf1d209af66dfa242ba7713b7f0d5b4fcaa73c6e6af62d3676c77474d88c451e19520f0b6783052e70e1f51b5a140b1b1584fac8ebbdb76d0bfe41712a982b82836c40ec4396ec084cbe92a0e925e798a4dc2e91fb6b07bde510e2f4b12731c4a6335e2762b8d65eb1a2ecf0d2a52698794ac293cf4a9c936d6eb21167d923daa11d3c112e3670fcf486bd40baaf37aff16314dc364ff74172f9deb94a70f8ab0ace974d6b22a15415476beb193199e8657ca7e4259e883c8736a975f9de2f7d3a2ad67dfa1169b4b2d83fc2c64799aa36797afb106970ddb63867eb8febcaf43efd467a28212f0f3208a2e9bf8f62dcb849091fc98d634796515e1db40f58d0a30d74a5d1056dd735d30aeb07f63c44614e131a6f0649dd2645560ff7ecdfbfa2700282d3d297054d3ea93657e5a39bbb7f2f1a563fb3f6792482d6afff95b6edf1c38e207d11e453b67996c378c22b8627bf04143d60e7858c07766e976b5e786441dc96ca44c584a32d00e64bc109fe2e0a59d039d73ee82eef1a50d6640c7dbaa4bcf7f232221eaf31c51de48761bc66722ff46a34ab567d562e60322ca9e501f8f4a7dc3eff3d264d59647c0ec9854d0c0c9d8e2d063766870976b4be7a52018cf109113a2b8b295f40a0604d0b31f0ba0cb395396f9ceb29c470d24f6e6d3d3dbc33ee78c2c8f3c47dbf2730bc131c9e1c2f9937dd796f6792b1d5998970b14876080c8e7f9035d63e246ce3e67f60d66e662d3f76e8195dd0d2c219e7115d79283645d0b9a1cf59d1e7e5a5e4163e11d755a2ba7975b983f40d59fba6956c73a79b64fd9f7c975cff311b0e2b8290f51ae2d086c782895878e68dff23bed99e4dbde108b46e5d0b6de55045dc34090282a5cf3e3df31a4e9ad37dce65585a6c72f3ba0e3ee15d8f68cea8356713015a001fef56079a8b4b934765ade73bed70aedb27a08c6f9dd0bef90fa4c7d119810b3e07dac414444df971824104bf43786f9337628322238e8886cf8ee02ec38b2c4ae42edfb0e95d3d354c82da8eadf476d145adf89917f619d32f126033e816f2b53fe8116641998305f48e86062d26cd9720722ab85aea392c804a3e136a00513be362e433eb1a8e9a5904ab3131665941b175c135031d7878c66dac7a010edb12c45e8cbce97837f122b2beb2159052313fe3f51148198b6d3c97851ea3ea26b87e92b7a16abf2c2c8c3a9717bca590ff3cc6d062055f14551e03895c64500eeb25f87e219832cf40f3cefda3d59bed69a39e5b46cf8f3f8a6c300122894954b95b3b8d995504ee81646da4301b6914066b1274f96b21386adae3b2ea22122315c59be277fd309e81995a84881954164ae1a59addb58c9edaadce1793320310e3dc955267341088e398c2d8397bf839833cafcaa94582e152b8ddcbf2c4bd45d17519614bd6de3a08a32e83492c2ae1285d26f667b41deefb6d401e29cb671281e2e06e79cc1ebf470e444da552bf0052db7d087907a06a50b633a6d0461f0ddec6ea2c71df74d85e3a920a77cb43c02f3126880febd1d20794315a4448177a4d2ffac04ab3aa0980a7c413c7baa6f8b097ac662bc104a4fb928e72602adbc4370795434ddf9f48f96a9c6a9227781069e209b826ded8c5239d0609f24b71d31f564dedc6edee96ef862e2a9fd559702a49bc61173023edc0ba2742f1b2278c85887953941d5a58720a2e2120d49bc3e7d6a7f2f00c6a039e137c77db5f7a7c3d43ad2eb0cd564af81a7584ceafd603e0a83823de3a12df635b795dee53cd93145df3bb8497da2b683e7523d859319dd4ff19f2cb01763e0c41574d584f4c5619f52b4b4cc2f2c74925043eea26754d5db6ca5c8b639e79ea8a09c39d1d4c436c0ec849450c1b66e450b3704fb8c9587297064fda4cda8d6be6e10c9a6bd089bbebf8decb1244fad182e6cab87fe3f3edff5c13efab840183db736e701e51f560c1e14827b42d738d37d68ffeca42dcd5466d50841dfdfc6aca437bcdc24884d471bbf20a6921a743c536bf01b2b385fed9a3f3626798cb577bdda634f8c158833e52d121b343dccbc31d3044092ca4cad39e913dfd32bcfee874afd9a02faf07ba7108c05c4beb78c050d5539eebc699fda08b360ea334814caf4fdced62f87c47d36c1fff5d8865992101069fb6679d3f3ac87b7e6e2587214105dc25f76c4a6779a1a9e6022ed9ad59ba3a7b4bcbbd0d63d2bc0674c5fe77fd4fb6a0ebf65b5a73bb87cd5b36dfb71e7a54ce2bf8d9b6a86057536c4a7f0a7c5820828a0280adbf0cfdded491fddcc8804eaf9fc5230d59906dc7a4ce514117f1a9bd0499dc065ac404512b0315a6ef17794bf296d9d371115f60a94015da2f50cb9ce4123b1ec8c0c94213ad8b7018dfa325e182a68602417c95eaf70789d521c9d3124621b36cb022e61f211b29baee96bc013270948a601fa1d3fc66eda9be473b3ec13fd0bcd59b06736e8296053a4758c7e7e1afc5111e1d43dd199aa708d95e548ff21c2d3e4328d43c9637baedb275fd9cda7d1225ef0d40864e6771e53bf5fa836121b4b6e9db6e1021d7bd93e5beef63af89b889ea83429abcae0bd9e1a079bc35e71ca54152c281e1a27921ba4e6b8f7594df32676d4762b82335f1097a92f49a86e5641bf1d77175a9476cd42f90aab18671bcd7c35dda9a1cb5da2f66bb80a5187abf85afb1557e0ca6052c63b6bf9627604823c3b6150eebf657089451bd04981691098092dea8cd5a26a693f0b38f42cdf42f831735869a15dbb3d0c322d85b0ba40017c4cd72e1a60d972a0d8f254e48fa6fc702a555f0f76598d1de2975eff26371fe13a6ee48da8252053ce0396f352191b416ee2f94dc847196def54f311f66896893495f0a013c04c442806c3d4e1f6320039db9bc1d94a51515344249b480087c7e3e937ab3124254c7824a99ca6b03f165d0fbd026a641ecf9e538f3aacf2dc6cfcec150aa7bb45acd5dd9f20e0a1d6ac2a2254a365130fb48f69fec83699413f5ee3e88b678c2b2d1dd316e5f8fdfd5a344c4241719f55e17f2ce1a4658067065efc4a4f970db9f1a52cb0ce7eea901c451ba95d6f2cad66610c33c9e1d63af3310db7e7cb85e3523c79dab34eab84296d7e2f610d23c4c9ace9387dd0d77ac3d37f1a35c78c7c31a7e55a9a4a95139fee0339c2647a56b32864060c43b9aa9b62888f4fbe09053dd5e5d9e71d311911f3ec864bab3f3ffae8c8b790cce1d8d45c3ed020ff01a827e851aa090338602920013e0ce3453104a8abb8e69717b2f7a9c1469bf0c23b79bf38c73231e7eb5537fdb2c677bcf1ccac3c37310738246641f4647721e7a3e165a187ac1400a0ee967ec60dad51eec6da1b858985345da8715284fdd876292493b21208d3d305ab93207c67180d217c22102011f824c7b15c92f2f32d6a39f9d9a17fe2874c84fc4456d39490dad28388e4ef46c602db21ed43054beed2f8ba71fbbc9d03c6dbdeb11327883a7be0c0e1c315d747c7d96a2a5c3d7d8000000000000000000000000000000000000000004070b0f1523", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 62, - "comment": "z_max above the limit", - "msg": "6e01000000000000000000000000000000000000000000000000000000000000", - "sig": "289ccd0e0e58656b8d32556fae8b0a317eefaff794b013ad8a43234658706a2db12585faa83808a733a3a88655a5d7e0201b8bfbbdd3bb545dc306806a26939aa9c93ba58f46ed8d9c37a9f6e0e0afa09f6c3b3f3abeeea3c613d122700fc91e88ffddd965df08430eb37fa28bca6db2886601e075f77bfecc67e415d1ba783a01c4776e9b96fc26a215084828b0921c90c59ef766bebf0210bacb23b7f26b8e572bae202b9131e725e367563c1b36218d63f8a2988dacbc73f4a46f313b97f660057bab41c1ddb99df76df8b22b16754c333ec2f141302bbd2a1e967c50882699860243af42b6ad5f368d245823a71c02a338ce037e337d4d8c5e2c2c7d54436ef786878e1e25304a27058d89e7212f688c50cb701395a5c2f0cb3310c9dd48777f80edb0d2a99a91f0a444296c1b4976b6161a9a43e5ab551b135e0dc66be2f06aafd8c50c109d413215ab4b39d3063e061cbcf57d2af9ff36f89f0c80d483af483673595824ed4c4c71a02ab8c4135a6791889b8e43958a5b509332e84b1380991d79c6397aae3cb3dc522a7da89e925b189a840c2ca9cec4cdfd8bd3831486d2c0d15b1b9bd44684a8aee873806610e9ae0fab2c61e1c0366f981d5a42bbe1d9cd179883f249a7a155b80bdeaa1cd017e9d3e0080ad03a93f09693da8773b1256b22c20a6531a9957ccff0bb44cf0ac3e5b0438949a589755d516fb2b596336c153dcbd5565b6786cbee057a41c10fb762c280e850accdf476392b50cbeb2d8e7f6a6856887e4a2098cd8f4264cdf39972add334a5aab45002058f19c6506069d7acecc184f245a25a1d242cdc41d52f2b3cfe23ba797c4bf87a33cb593963179e5fb08ac5edc5d4521af466cc3c28e6a11ab2f5f8d06d668fed5b09a7f3f6686dca450467c8ce0b8e81ef605ade33349dd1582adcefec138f004df5057b2a54173fc587ebc3de699506d19e61380291fd59e50a8620f1c9c2424f80a48cb1c342534f26f50e52ca4056c315348dadd204467bbb485708007cc2d8477c518047c42a5c7bcf83e763297a2e4e0fbf547b4e3e577c2bca76762b35d3b849966c9a0e9d5cf570bedc0ff1b779148fa125566b67d14b62421761abb1eb04a9fef43c08d9dc793585fd30330d3cb1b4651ede3121e836cf427dc6f93b4dbcd1d3d0b096be780cf6318aa31d23f6353a86da38b34265b277b7710a025e0e91b7133d08f5ded6d74efc88a4f40bd256a6c6f86d4b869e27953a6c1a40d19f76311b48e3be34973e65f17afe1c408062da2e2a8c474c6a3cf32adec928c4adfd9611671f8b04538f7605ce6afe0d7836ecb06913555b730337bb19a222d3a7be5ce8ac44db76a79120ffc7dfa81c07590955587e61828f782e176003dbc8fcc38fffaee982f61e3bb503ffcc44806a23d3e480b4fc5d17c630b2b5855d67e884d6a2ace9e0ce81a7a0d127dfba247bf7b90634f03049d7aebc1419eb4e7b2ba3303dfd3a28fe5d42a73a7e190df163cd241bca717679c819a5bfeb11ff46e06c46c4c9fee4005a466a9e8660e01d050fe1c103d73bf6927e0ebe4c14b314b3d9300362b67ba5f0dc334a334eef48fc248a7604269dbd9dbc0a380af5ef51a91a48689d190d152213a818df7965e4ffb87b3bb7b65fd2ddd35e947789710c898e95b431c0765cff907b61a799d65e2cc99c5696777e703d3d6459a71901c0080c57c636d21fb0c9d1846e356e0e3cc7a6518ac177a61cac9b6ffa8b72cc77bbb86165303813c21c750f2b930c240e4e1a3a5b1801d1c8f4d8e4ed2e205e9b99fea36b0a26e015ebf7dacb547c17a847d495d5d35828683f1432cbbac95d3b5c77b151bddec5fdac911de1f096cde0baec71e5bafd5fa93a4a42185a4f324ad14a7165a38d659155c4afc72e1591689da8f152d2c7836f3ded5e31931b3a31eaeb83362f2f48e04d1951c06916f557289b01ce62592bb97122c110d9b608a181141b78e5ac37171f424041ac9d7c56e6d85fc635279d81bcd9ca023859bd152074b07337cafb0756a2532d2c023e45cb48fafa19030b0b0d79aef3f4576e35ff822e7cd014fb9d298dfa6a7e8dfd4ce2c52ccb88026a620e985a170535425c01695f3b71bc67a9c3bfde4b7035498378c9fae3921a087148cc61ca84953dc6e86e07f6056d9d16f2b4220fbb1b905a1a89ca8325e3d7afa5c18533bd478f47aa69c7d0d1d1f75cbc093cba23c439aacd1911b152107155462ec9ccc893448620ff2d24ac6d4c0d3694de957c53fd21d8f7b83e7cc2ded752b61ddeb1a222fd6b9576e6704d0d1adacfc963cfb5844df234d7eb97754a1c559fe81b4e64907166ccae5f581a4f8b90bc63e478b02a7d6194e3607a1dbce74fe2aec7eb63ecf484ba30399fe1315e59dc2c97f9f6cd188164cae2623da7c83bf96031bf14812612d8bc940cfdce410c7cd5f4668764051b82327822fca43cd49f35db19e1d79765ca4b662c8bf1bbeb180776867021054c3461619bc477c70e6fb36b80feb206a003ed12c3984ecc328d4d476b66a402de1a711d9895700897679a2c6bd8481794ae3da3bf011ba67873757eff29c135085533139b01f3a83a5504bacfe73cdb48acfb08357397c7d612ba4811fbbe51c9a18d50cfc530616622ca8e2f06801473538286ebc46a04c877b72eb8655b4b6c5cc9bac27bf6490c5f593dd020c5d30bb462023381cf1fac19d71e9701c49d539244e5a9922807ebcb11224cf0ebaae37262184c61774df08726981ca49531e417c90e51df7965d0f8508e525bf9cf4c6027d74a11f8141b777da862e50af076572f4c78026c7fd6b565624fe0e2fcf3111b3373f854bad57006f276588c9ad57bda5cb5a0e02e659cd0dbcfdc174a1639e6c9046516d916534cbe5aacc933ac4abe52295c8533a4a1051b5cb4dee48055e7e1d1bcf2154e1ac81a54f1f54fed9b920ffbc2accc896ba0ddeac418a71576aeb9abc0ab3a0bc15e57787ce0fcbc868ff2545a83e27ae616f2fb5939de3b71bc9ec5a2f064a736ea3e4afc1c8b5996f0ded8502c5a16317daeee9ce8320ca4346b5434769ad9b8784898599508e173d7f14d1232a2f84ddb1fcfd8de75bb0d59f8507214df21e89762bebfc4030bf0c9239cd7b6bdc4085f1a71e732a01c0e2024d13e64eb0b582bbe36a214454bbb51eea590ece8d1f81c95891ba8f203ea52c068bda155ea6f992ff1eb276a11c584b5394e562bf6341829fef1936397aefe78264fa7b9b3055c3140cb4635f20b3e4dc809e4e48ab4520253330a35360ed41ea3eecc0ed7c4f77c6d86b507934c8b800a0ef652962d6d4a5d810ed17643e950e3025cff4bdd524c8dc19b9a56e3c79c6d5e106e4e199968660588a063bd3ee369ca6f8c0e7f2034caee4ae4824ec663c4fb485c81df7ea86d7226be80d5e63b3782076a9bcd0f253c3564032f7c82c22050607ec01831f2d5a78f197681365bdedbeb6076037a88aac92733087a110dea7d6103ffe6b8596d70032b903d1e619494797d6e56e133538f80a91d305b07ff4ff718ac8fe0452bb3314f89555d81526a02cf189326861c4248a40866faeabe04cc1a7c88196c6d4fb3fe2af385212a3cff398caf2be65e7576befab7624f1e9f71c285899207c2efd2bfce2ae6ab9fcc6e46c42b028c857a86dcc944739ac4fcdba51b16dea3672149f166ec8e5e6913bc355208e3a73b89480e83890f0e4331aab624ddff3a103fbc4990de6ef8a2a48eeae86d7c6fcb136aaa52860e41a135a50395e12511635dd7dba11281c410173ab8df4408c9a2b51b9c1e0ad9655062957ef4d8f0572afeb829ec443825c082d67866618946f2962f6541c6b5ed1528cb410521e493680e9d937a50ecc0c50784233358a534e8bdb0c922e6a89b179d2299c47c26fd9f3c783514ea19a87b14694211e55ee9e4714bf5808c4da9a9605b12c53148e52014b5983e03eb47755ad4770bd54dd1b071c9ed0c4cf24103973b815d267f3512275e066f39c2c219c475018e0191c5d18457a2f4f224fad67deb3333620fcf48f4b4df62f358960b56387a501e69ace7d6b438af7550d6831d58f0f642630d3ad590c9a588e25610a963ac2577f67ede49878d87a30e69da83c6ee600022f87072b9618137c029ec6292d03b21f54ceac63f740c5a5b938b5c28cbe6720d55bbc43fd9cf915bc199f32911dfcc8642186b06988443e1c557a4713570505ff98b0c516db185da76eafa1aef72732816ff31f1a829798d1a5df2218649013a1463984e585952ef618e31ca2208b162687d7cd723e0b933fa373e3d795355ce1bdf5cbc74e8b2a43b72ea36dfff3cc7e21a4e117829f2f547fa475cd776600967b0c0db0bda413cb905c86eeee28bbb4f1f1dd29bb283a43cd04d2661f069077989a1eb7fbf2c709b304cd9fc3277f86d85b2012270e6fb2d083a814388622548c999938f1d52f3f9f532a9632787bcf8a63c6ddd5e5cef2d19e635579273ecb0b43670f12bf0e93793ff345afc2c49bfced401152f334188310c4fa83f7d3f67b6008e98d1ef9dc383541b466176bc166a0a1928b99443b94c585a5c71727b8096afb4b6dffd293093c8ca0e1028667797cdd4f80a154a5d94b2f662748bacf306345265c2db0000000000000000000e131c23282e", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 63, - "comment": "r0_max below the limit", - "msg": "3c00000000000000000000000000000000000000000000000000000000000000", - "sig": "8c5c7a82862de1800a34b8201c791d6c7288225427f7deb02f52748a35a8ac269104927b4913e528717ea107ef8605f9b7ae265f798846a3abf6bbe7bfe0a4d6bef6a1f6b49d40b972a5a1c28d19db196f709b4d962fdc646a7988f80d5af74b29adf34c7a1aac065f639925423d37bdaec428de53efce1db750fc2686af90ccc9e2865497b7cf736829981afc749e85e7e9b5044a92b9ada3740e3fb39251c5bc400379c4ded2615bc3deaafc54e34129b5cd1f4e9612964d353546ee5dcdfba712d985cffec78e74bb2e6c12ab45233ab42f19aa095ea0082063fd0fc8e1023ba1bba2b4816f011c644be94382af44cb7f40c27236ea1e1e6f49ded751927fea168d5a5b2f238360835adabeb4d1b1ce12ccc6c1b8e1e855cfe323d89c34a1a683360ce9189db6a9a93bfa5f70b7238d7f796757d547c31f786c9bf1c91546b325a05034cccd586a6f37879fafc6973fb02a540cf84d1a4f4c3f3ccaea925567b9571bdc116cbb14c884fbe35974980121f7d1e6b0413fc3cdc42dd4fdfa4c33d2eb774b3b188c3a2f2ef07f36489e80027bf5a9e3b607ca45839bbddd9370c9dc98efabe00635622562ce4a12c7c6e2271876f880b8d8a9a63e5c10f349490f982e5215dd94bbb74bca994aae7143c22285c5a15ab950ded53059821a526f6f10fa3feaac97c8b83453b20f314e8cc509fde7f5daba0b2cf4676a9286e1d9ff51f7674decfe2ea54c11a9562b34bc15577cd591088e5abb0e49c152135ab4d496d8f7abbbedc1f332a06d7ba9d9a65ba61b1bf3bf67f9a191c96be2b51d790f8dfa988d9e69a5ff9484967d5fd33b0d7e004a73839a9603dfe2bd2d1f838fea9aa15c9bb2c0f2dec02d17a3041d6e4291bd7d4c00ace00ee1f4a6dbc5e4f76fe39fb4ed231b5df55f7a42b9366396816b5c372975d5fba004a20a7649341859903760ce8fa444945136f9ad67017cc70d3f6c4d8ef7459f1a544dd93d135b888ac4b0f6cee4daf45a436e967f76ec477c8efecad626da1070ff4ab94dda6bf04d19a5391333a2ec6033e780e6b3c9575e9281423489db02201ad6867b3e36e1f462e6b196a2410206a71073f19d707ac63320bade5c6c42e2998c55da602098695db63144da3f9a9f38b53022df84ddf8777a19d678659e44e35f3d8e069adeabe7b79856f8796453f3a413b4ac93d87ddc119d82ff235cad30c561138fda8b0310cefdce08d4fc7794e964df23d5f153a711fb73f694ddbba93cc63902fde5488d318f5359b77ba076337ca43ce59c4a9012ef52d86c34411dbaeb3fb2edb4a70199885d9e04e019c4a406817b96d478acc29f5db9b4cce0da8474bddd09619198d97b3609ac1a3161e75ee485cb6830c307436ee1c48d80290cabe41f3d4b881c4af4b2c2d82f4b6adc9fe6a1532e39b96350f7fe82a23bbd1d9516e1d25f089cc085c5c72b880f0306f73b5ac1fc805b0dc5e80506e06d965f55485fa61fe6e9ef0338e9de6bba5bacc703eee361de69b3264c280d75ed858f736ce9815344c859ec67a95048cb5dc03e328e9d10ebc6d3dffce0765c3fdcf5861c5de3aa7a607bf78334e8d7ba00daaa7ade8f79060b1e57b9d46bd6f448509934debd4e23eae219e04e828d316b77ef5f15041f3945b1a98374d1c47fdfec4e4714cdd7d2391df6670b164805b0a95b2f31d937446a058a8f3a8e968d0da62b8299405fada9e67e001b6e30cc4687120fa759cbb390237cd7acefb0e474dd95d9d790423bb19c390f233e3f8b7739342fb2adfd623d4c780a5d1e702b8efe91e0be39a61a8a93e48a0d730814954a41d472e6395999c828a98d5d9bef23ee7dfbec1c27a79cc8edd035adc5763eae1ede0bf16235b8da7616c4882a6724bfe2f7745dd992accbfe90d1af3e8ce26a9a63701089151f4ca826e59bbcdf40935e6d3b55329d757dd3461ea78f6bb109389b92e41c5d18f811e783779f1dc3a14f0f3e30a15bd7b377c1bcccf621127865f66f64231a4c77a913d2f9f5319028a1d585ed38835df077e0fd0f6101a5b110650992f029bf70b151189acefa1b4584f5d56676c401804a6dcaf7b18d43078089d580eb6632c4757ab77c6c5fe3b28e3a1dd0aff4d00584235b2515971b9644d100f488ec980e1f86188526a37d6343db87f23ec9424c900404a0d4b133df270cccf54338ef5d6e0bd7a2359a0a892829ec8a1bd8f8529a55ceddd1f343ed20e08a0a0b68e3df9b22e1201b1ddd8184e7168e12196f84885d317fa0102753e6dee29a5203d2206fd6eb094b60a58fb3b0a5a59b4cc109e948823781ec9bb364ddbaafb1d553dd4933191b0ad56b7bf3398a4b1269aa329e47646f4e9d97e3aa2fe320efea245db47b63d0c36266c3f7d1c2b51271b06dd995e7bf6abfe861acdaa3534e9c2fc090988276257228c7338209f2cbd77f85b8182150d3287bed5934dec2a6c1d7b2b670716cb35299234fd94070a394868d95c5aa4d92ef9ec6fd05e80747d7d69522cf5d5e4d0dfae512f25d51c0d5a61bb43fcf060eaac8847fc6388377b1f260171ebdc24373a2a177b568f08779ebff6204f2cea49afcd8bb298ceb4f751d69e9bf840b567a1614871d72f5decdc8dc5808c2bdc41c5793e1811b99d3daa9bc4827c69d1dcc4cb55bc8c6366764b96a3114c093892c9e2f1a736f4ed3ef2024360253612747ed4cd3c690b98f65faa23979cb9a65e8122dd30a9c1f2cc3ac1d77783a3014ee64690a62567769cc43252ff23563c3eb4803678edd7a83701412809d343aa4ab428b6a1132b1d559f84063911832be2dfacab5836148ad7ff94ca08afff9835e69f216209aad727ae19ba24b9520bd59ec6b515c328e512e210d6edc9d8d78729bfeae0743e333d731a2b981bf5408239446ba16f37300ebe23bddf746090e4ab57290d2d1eaf1285eb62b968bdec6f5b8bdda4edfbe55cd1d974e2924289366c1f2cc38eadf153cc1666dda976d0fac32285962fb4e5ca87171062aa2a98fd7b447b7271b93abdd28d88020230f973ed7aace2302a321312233927fbcd390ac217a8252a338ffabea7b94051cb03255d04d538e5998c72027251e7f36ade0058eee853461e8e36824055a63d5ddebf3cead8033dd5c8ccea4783675d8deba1cee201dd2154636baaed297786d9b1299b43f058e5649fb01bde625c415656c30bc7c2213d82e83754d43d77b5af9cd2d04642ded3a25cc8da578ccf437aaddb39bf0db269e2e2fbe90723f18b56fc97325d57bb6b8155241baa4a784423fcb50ac5092070a76ef4895209a94f33a4072af0c3c458077be24ddc153449883b3bd6ed3da6e6be85442be7bfd96c0700c46dd79118f67f30d6eeb519323d3057da380fc0cebd9ac6d0299c9ec26f32c04bd8752f710dcdaf2f4ab235f196ad0e54c2f05e825b7d6e1634f3dae1895e4b55fada1eeccf0203d23042111c4043739cbb1b823f6cb7e5ebfa4a8359eb7511dc64ac0efb6a0c6231418e5432123f6a25f4a9f35dadfbdc10f502620e6d76ef9a72f893d76ea7875d909efff9be03400aa8a1e00db7c07cd4fbc844c8b8e86345d49e6e916066d07e06edd980176d4af31d6ab20115b3f20e32f17bc565b2f95f3709d5837fb1f7ec5a0dbc12a8f7d3eb4e7f9f9b6744e4864c343147414b4c104116e63ccb61b5af3f7c5db8b5c05b475cc7f39b888b57298051d029ce9017bde03041abf0c91f32f28a834fa95d60cec9a585c74921f60eba40f13b02de973d9f5499c9b386a5348414d333adce8bf4717d5f31faa4b3e96e91dccf7512980b8cce54ea4be82ad1dbb8373355f45ed6861b08368f9b86f86c35ddee6daa1a336d1c4d2d2658a15bfc76fb462dc0b7c36e97eb16e5eb0773e95581199ed2f7c4c219cc4095d2f8e6ca444d6d4c0754bd39b5494af3d2a01db862cacb1cd2225af884a43e5fa4fe63e5854d3d32f47a8e7af2991d26fff530fe8d57d35ea76a9431a9335fa1f057232f69ad89efdced883e6f8cc23baa485642272c515ddfe4524b3a997e173a22eeb008ba9c16adfa3830980945c758fe92eca8a96b32b274825e2688c11883d138e5d695b10f58f2e2c6931764c91edcdc40d56c72756c1e20494ab26986ebcdb2309060f4eafede1eeababa4d5da8418397a25309d19937dff876ccbe7eff4b58b87a44cddc3c8b1c4f066746036452caa32980e224b53eff0379700a30599aa2372ac4dc081020cb364546484dcbaeb8c3adb6d3ae4a9817dc2d987a690c8eae1863d38d3458f817618edf6416a71b6c30c928d5a6da732c6dffe56d7105141d5941e02bcdd55689892f0e77b9623fb065c17edd799a186f80b686ae5bec88e4f16b05923c1515447ad9c82adca69800a6b372e406b6bf5b5282480823183811a512ef5dfc0b21eb77048091ef023ae281dacdc1ba7d1ed2d9df6811dd5d1c9a1d4f1781b74ff1828a6d410eac1b54a5c251c055ec7f84cf22e3e96cdaefb8a9fb9c6ec823ccf141d2f6dbd1f589c0ec4102f6e91b3f0610cbed643c68824e7159920f52098ae33b5798ab95521f869f2b958691c4a0926ada90bf7c6678f23314479df021214537aa6aab7bb183154b7d8ddfc1431616793bdd541b8d1e1f10124263435606688f200000000000000000000000000050e151c212a", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 64, - "comment": "r0_max above the limit", - "msg": "6400000000000000000000000000000000000000000000000000000000000000", - "sig": "44f2fae55e75d4a14261c55d3b8f9d7ce296180728713a3374dc857bae406918542bfc12db9b25fd3d1928c9927b72be345024145c41d3689654b26e1d2d6364395c150047eb8b6ce89daaedb70d8095263514fa5317af3f6c557a0b91bad5e2fb6202f90183d2e1d545f5a09fd2f5cd5550e349e82435d55deec6424abde2e6cda6f794738180260c45999b51f9aa2cab98694b8d0af27441fc4b57289e7ea07b010c53e9a755ccb9016765990942a3d389500cacbec33eed059d412435ddbf46198e3c747b3f41f96dcc879ed3056b20da470062c0e1724112f48aadcbb6ca84e66c4af1418c66ee6115fe736305ac9f177f2fc8eac53d494d24164760e827a45ea20deae2034dfef4f8b552a0b4167e1f6272918221d4610d1278aa7040079672d2d191bbb19b252f84f0cdd46150d7be832db3fc8018aed6087b5e718bbb7b3386266d122ed0f27bc5b746651316620ccae5543f993fd5e1cc62990714e585878fbf20c81bb45edd5cba6de67010ece4135117baac8522ef59ddeac03ddc9abd91b47cefa3beac2496de163c00716956589bf84ff85e0732ed2073d97c5c34a0878c3d329e99a5a5a1be3781fff22646f1bb83ebc311889a56d6def19b8a86fb8553b36a62e13cbba15a507750795119ee309577fa7ec15a69be34a15135095730ae2ffdd72a1cf6a9bb61b221531cbfa0495200ed9f471ed1bcef9cb8bc5117c6d6806bf28dbeaf52bf2a9329119c5c896449c233c4a314076b00616773b87d9e8aa69c135a7d24c51c2acbc6e58df8bb7b6fca5fb14b13c9d0b33acd8e8b439a8e5d5bc31cb5bdb51712d148f935b8728ff46112ba49ea5af30150fa80a8249a2ccfc99f8b7c897d83c428fb15e6cc6e640a697d8fc6672098aec99630250a7b82075296afc00a15507605a5dc0f2b1a0375b263c53c403883f42a0304b99adaf834b1f2599e22125881d87047b8acce7b5728158d178649cd7a16d912177623c637500dc5b4bd13bcda0824fe377086862bae9a41c180ac807896c1371a78326cdfba763946ba608400d930146bf86efa861be282f44bce6e032bf7d98408c3b4a1e96704034ffba07c182fabdf4014ef2ee8ff8ef7e837ad75dc3aafb066d07297a290af9573be900b68db9b6c2746dc0d2b1e5d11f0540d170571ed530caf1033e8a32beffe622e3d082b3bc081b3c30d8e1dd697e9a18432f2514df6f90b9b42cc2c1d321f6f9bfe095ea7229c4d1825c8db8e869b56a40cfcb924304f8eeebde54d615521ebc9753c95e9831556c854fa163990d5015e0370f5d3e5b4ae7c4404c18ee125ea2fda5ac43127ad07567c44c806ee61a79353152c5f46bd98bd2010a53acdc66df92ee6fc0f93e678bf44d5d3c8e9adc305bede02008bde91dcec639554a4dbc4f6625571cb5ec821f2848ed33fceff30d8728880956a1581b5277fd51a61d4e13f7871198b78ab3107701163da8a30b379a05718aa79bb01b528c187fa91466588961f2e58db24a2afbf0226359a4e6c3da0fc8cca4be25f0abae106eaf8e1de7ce9f1b7d24ef25bd41aa98a99610b016f062d89f678142b9c27635cb71e9dad2ec332350f76a2b507c8fed9a17e60e19de2c1875f2b3f4134b903aab8819af224fb7eada88c67875040a07699d95756ba929680191ec8ec3efafc6fedd60ccc1e1300698bf56afaa31c89d16341f3673fe07880e7009e1f5173cf79cf0364f0833a179b5886226bf8f3a6397d8b499e9c020ccfe075fee18769fe9f7765ebb6ee630df990c579580f3910e704c73ad61512a9d47507e8bc61b9a61ac006b751882b20855e6b6ec7c05e303ae533623bc0a8d30f795ae93f057c7e079688b792456deb50dc7ba9da0e141cfc76ad0a902bdb1d032d06fa47a817d43ee784cf0ca4b516806e7631e40bf0671b3bdbcce7e2ed7ecfd994e190c9e500356d60e1c73850cf5b6bcaff9746b3025815bcafae19f20468591b5114d465a47e7e439ec0741eaf533d5ab5c57df0cf745931ca6a4051bba72dccd4160bed42fae52ba39d7ee2d3e2cd20fd299707e2a6228f94a5d32224405a1dbc5f5f0d269a0880cae9f0b7d5c0ddcc01e568a03208dafc9f54e715520ac51eef04d8c4b6fd5ed23dbdc9259029129b1b5707bb197920ce1265bacf2a7a7f81b77a017976c3a51b169eaf6f77fc68ad23e2edc7a07e7d39908704123b2385011d9e6b56eda29a8bee801228e3677241121ca21efab92227475998de40d40fe76412fbdc35449255843e3e6ce620ca0dc91075fbea5e531aeb9db6cb5153c61e7f55681eb46cf49b31b2efecdcdeca7539e8b3da30519640913672164575cb1ce89d2afa22da971c371f602070e2b1c7488f89239918a5f0df2257e8206ce67106d66f308cee488974e56ff840e025140014bc776211d632413152fd55b53749262c477229da729c1e56f885f61d1afefbe11f8e5038a5688835f3842235091f7bd42b908097a8106e4760259ed7464c0dd591ce48e51397bda9f3514b443a138a115eadc2be7f08edb4c9dfc9f1f065430bd9da0849c45dce861bfe839954131fde47e059c5f933a4baf982e0ec435a8230fb3eebc9ecf7ea65d0f376854c331fafadd45b07ebbf3041cf079300a9dee19a5854e147eb9c88300f5580c54d5801af62f9a90bd91da9f52cfa6d01a08ce390a179bfd6a0d3ba8e43408826cc36fabe685e9a1229343e5303b108683a75c9a524eb776336d0687e7e62bd68f4d425bfe7e4db1dcf09fa4938933f78387e48fffd47669233cae1e8bf9d4a2c63444a776595a48b3471a67990257cf7a0417d34f553eaf423f1cc206a9257f1aed004bd205dc1e7f660aeba09dc1f9991062665d38c0e2a4638c2bf61eb459e5e4725a0bbccbddfd66b239b31c62c948a485c8041ea3b6e58a0090bcc010ceaaedf7a2e8cb28cc23c925724f099ca14a33f42ecce7584bdc073e6f79ced17b8c113075f1604f31362893a3b5ec2a4953d77b68281c001fdbc6a853f4fea04c1e73b9bde7bead3aed35ef68e0ad98f902d7a7750b7461ebea8c2b7e9246c49b585107e979dd66c01969c65d34c22ffed12ce733d3543672a59a06854fa81187f3a0b82524686beb3a84c480aaae6af5a43d6c943702e49865935065f972c466e2e33554615f242fa582e04b7a330d84d5352b5a0c1a28c8521eff8baabdff6c35450ed9609fcde9291d0d38d7cc23d662a6261aed3ef34cc281501d9969425a42f050c7e6b0b1f3a549d7ef86cd1a4aac3a233ecc36cfc2a81cd69d951c31290eb73c71582bbacbcb99f3c29fe15d28887349c9aa2496b48ece89d581c697590efdd60351def42770f51f59d55bce58c5d2886d2ccc668237f9230a155be656b2ba71f58ee343317c7f37ce47f5736d99a056ed3e88ba59581b9b219b7e972b96b2e03cbee95fe9a2ef42694bd93e7e9145ebb155b6b9a7590058eea44d1e877254d55d052f9979ec0df8b5b8cfcdc1c858ad12d4495437a5c8247a071997f95e01943207be1ab6069e7925ee2e6e231a2f133177d0a91478c37c19303097971af66759f0eeea69028de913edc1ce9cd38edbd05c3b7cb393ec781ee7263652cdbb3201527501b60b7ca443cab817e829eafbe49c354bba16c1a597703953ec059efc97ca0f1bcf4bb2ba59e5bfbf64b5cef5dd1a7cdcfa40348b5f8979e96371bdcfed5bc9a5036955a40ebba28d1c5d98e592a046320e3ff7e2b72d25db20fb2daae4e580353598ad6673163fa3eb95f5b5561a38fb1ba8fad671795e7f5aaabbeeaefc4a7962475d8b7df0fb93c47aefd46d88a25397f6be11fdc4014389121c20750e80168565771dd932f67866387050d0551664a16b350e4761d6033e4746d7a5cb07b65ad4c13fc7e64a60ab9849ee9980855106c7706253551072105e28ee78b6e19e9f9b25bd39493736a2efb2cfb7416b84b6de23cd559663c2eb8b223f8c764ee4298c75f7f068824c31d4c19cfe9ddf3871f7160c87d9565c5d67e9142f151a33e2f9ea79702c6a7285ff963dfaa68b4129233daeb77e0aa2c1ccc75ff7a35793b2fadf60a9b1b9074f92eba1cff230c461f1bb486b3e9caa0b617abac2d963434ebae2e8ba39b238a167895430f5c6eb86d93d678ed1c472c3f3e9cd58f27f24d124df2371e98fb08442296592d79db40a6f388f85c050e7c434630ba353245692d549166727c31955ed60be469cf60ea09909f92ca87d5e77567036882b11c04f03bdf89d397513adf17146d52802b86797815316c2d21d0b1e95e671fc87e067d2e7871c28257af1fce14533d30dadd947ae2b1b9b78eb56278340cce5ca9a17271e1ff03670d31ea801cb89d6364c0d6b671d190d75c7335ba00497bf43ff1de81ba5faab2dce55f29561d13cd236507a88f942e6feb9e77a552942f6bb53c857f192c126d3f1ac53845f54fab0a3114f6bf3dc6dc251d39174c0f732dd9c5301cbd39a2d7fbabbdfe0a1049532cd378c9ae999700ef370a49206f7f7b208c7fc7318056cbba332b9c73e0165c97fd25f73f156750448c5b361c30e23229f2c325a99fe19df3d884418ba1d1f00708204a778ac9dde7224f687b7d98e3e4e51a244e7ba5c3c4f00a12182c335b60da3188bce200000000000000000000000000040d161e262a", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 65, - "comment": "h_ones below the limit", - "msg": "2d05000000000000000000000000000000000000000000000000000000000000", - "sig": "1ca68ce5f7e559793f67c657ac20bb8f3117f28c1ef02b8b828031fe11b146ff61ac67fee066d1a8b9a8d8219909195136ac9afa30909309cd43e54c18f08817c526bb135685d328549f2d0f0d8c73a45606f93e8a17fa3528a1ee64377165c7b98f3fdb6a32fe920c38863d913ed398dbe085a7ac406da7ae2baca87f922a2d5b43601a70d3aee3f182cf87aad2de0e104044dab4fd19e7121ff5cb459595d002f4882753159c7c6421ea7e6f02746f38bc424d92b8c3b353592ca7ea3703d27d58f2df3b23875eb7206b4f983873fb230979083b70ec1e5fd40afb5e3887d05e4eaef8f833339be930c2cff359cc4cdf3fd6e7caa647f3478cc863716f01310a30233bca62a32cedff973c8fdac419fec93342f71e74934799345a6797e85a7c1ccf660fee8ff6402e3c37a70771a26c9ffc9411e745d6962011b003c19e8e267b303ee53079e23979f7b6fb4b5b5a3df866f68421db2bc2eb29fbd6c40d5d73e7570c22b425f5cca416af86f4911766694bcd7d9f55acee1d9ba8f6ac07e2b0d1081948e1436da0af1e622e95e35a2e39065a782e3efa36e0b130b4f22b37ef2670e6b5797826515ca74a9a1ada669cb6d43448baa8a77a9e052e5492fff23ea68698a17cdda1a4cfea63f9c186f35369e57a6f54a161cf569cc75be9347efa9c94a869461ff2648ff1a3c984c67eaf53041edbb4d27c80c9bda409039303052639062dcfe8c7d8066995c49e5629bd0ee47b63b637b14f7ab0964f4adeacd6b139ec3af6530b6147741ece4ce206f9a24d8254af20eb933324b55e911a43cca36704427b8b37b5deecdc0da5d1758de2bf8f6fe639448b45e803df46427adfd6b3bbefc9b9c64deadfb60fd2fe6788f7d65f98aabc960ecbb8f8ed9593ab0a6a2c7d093d74ec17710ee5c98909e529847d7cbe9a69f54628017c0c2222b4ac46134281990b9bd70ba991336de07133ae25701a91306e0dccca6391816917698aa67c39998437325e39ef1f7e8eda0dd330671dd6cca57f3f99c162a54bb23992e44f3b6310de3c8b3d309e203e0e47f05b726d1949cae0abacf838c31fcbf449d7f9d6413bd911c70a823c8940aeb59b7cbb2c64c243a0fb8ead3903ab3186c6390b2678eea04d18a9405c733035ee58f79f85182c520163e7e0b4bfdc03d60034dfaf61644c32bc4cc32beb4fd77419ada027dda3d6f30bb3acf38a8bd4cac6425783b710d5238496331a04b6ad5646d3ee663ea0e50da36b453771976d2e36e0be3d10268459724bbba557505a7e804a088e82e99367508eb5e61919a8ff35eac38903de0529571dea43676e3d2b769f4baf4c1226ed921561817746ad04ea9d30cba41225965f1f29bae6b0bb3e15a59e82e50c0211f22403957d86927bb98fb48ee18260df408ff629730eb5f967bf25af2bf4147be41a5da2421ffea70796b77944479fb15a0890785bad4c0f86603deca9b71b72c6b75879b44f153fdd80412cc8c217ff04f4fb9b8662c9d3474598f806d71ef214784ae54a537c307cc1373161ae471034f70b49b6a574fa6204d7997ffa75a78ab9923850f3fc4419fe365dc4732ac4ba87db246c90466741cab4ff9c3d39cee643e006f35b76ff5cbfaace83482d26dcfb98ed007b97f0b80849ad04e1d422a8c86120d1d90099582703402dc3d8bc192bba4ee993dbfc3b7c567cc6f5e761a5cc0ccfa92fc842a31ee0ce234bcd6888c8ef81e7bbf40956e3855507e2544202e66dbb476faab34c635ff8c873bac2727b5fc4730bbf33c5bdd2f3391181eadf5f54682e13a97f0a06487232da578c89960ad67ff424215020f3fcfa25ec55db2b2d46d3646ffbd9354dd14008512e38e523285e426fcdabd8716883ddfb8db0dfd4c036b51625b26a1469fbf2282b943500a165b6275eac29ea4142afd22d647a4ba6d458a65292a64e21afa38ee30120bd49aa8a0c511f2c202293c717259a07549b12273566f3bbf4aab1ef6c076b0e68fac0d3e777e1f6cca2e75d68fe5a45e5f045b891cda173fd32d54962336e33c25a5c3b03b772403bf8ce296282b779fe439396cf995d3f81eb6b069edf19b57cb1252dd611ffa52eb0023b553b343a028ac241e4e9652f7d73ca9cebd3e3642640ecb9f648fd1cd1f6e7701fef3a551bf60ab3d4f59315cc2b0a9642e5f4e453af47039dc0c95778f2cadc0fa217c3423c2063eaab0922ddc59835a4706136d6e2d0d25f7dd8bbbd7a939e1afa2cc17194430e38b2f983e5e058c9b8baa385ff584846f7862469f5e3c71cbdcbd726ed45b92998b89d83c6d4731bf2f92fcfa454bbe3c7313c9dbbc65708ffa3d9bd8b43df4d088de3c911cecc5cdd415d587310a2c8d3dc10782458c7205419028fef4d2adfc14a55fe7e4507351044820f9d40da5077a93e923f14bb1d12181298c6aa965fd76319052d148a357b8d27b240dcc143fc579889ceb43b8e7db8deea958671b18906c01d5d8962952152eb8245f98229fc2e0477541faa3a57529e2328f27614b7b82abd506d276495522fc21b2f840e34f20cc7d605a986632052ce8e47889667edc1e4d009f9f2f6fc6e4f59ef42dcc97ec813b36c412e31856478e1fbf740ca8933632c62b02d2facea1c5e7936d3cd7971ce35227c5138c5a57e032aab24ae4c6b05ffa7d4df3181fee7b14668f07aec969300c7b0b1216c17de4def301717d4ec65041d4656b96ef7b40fa4c5113c58e265a2c02bd64f7aef278a6f5c57b2eb35fb69dbacc412cf60e06681f892e4fcd7dcb3b6a16d38b7d7b54815ecfa9c1a0bb46138959bc42df552110f5f697de1ace36c45cee32ebc9fe8fe8cd83e29ca331f85898d55fa4bdde5cf438f9bd0ddc711f516fb0e79510243debe71df2a2ac140c19b945841e8ff6baea4ce9dcf038b5a0a19e0cbc90b3c4f3d444813ac7f70b0624bc70a0251675cd9f44b30b38aee30ffedabe5aef29597820cdf2bcbaaf99ee09f9b18fe93268d5c74f44dc77dfc721511f55295e03bcda9956cb74a9bd85cd028ec05b4d064ed35a2ecfd3f674e34cca9f972824b1d7d3a1caea6fd6b51a205fa85de4b44a2f92a45edb712c73a4d10214623e8cdf3b9880cd25ac2dac328c3f54016eb98569ece9dac6f170cd7daaf37d41e6c35d62c3db46a24f2e6f5f237314000d0ef6825a9dc987379d9405547eb27c6d631fab06d5a039d47dd2b1dc63a077b4129f7610458cdad28b849fc68fd5f0c6fbb40fae533a5d8b559355b1db112a5203b321012b126fc6d5181cbf6f3ab8de483824ac07734370701b08b295362eea3073efc3a96ac9a9ee3082ab49afa034accdfced6c16c8d6a7e88b913b38468fc104f0f458a298f0c352b04eb664b1eddd9d76f308a9a29fca3f3fb730f8d1d48db53c23243c8f84c06a91acfb86cb2dcf2b1ef3a0b9b2cb1f4909f48e9f9eff93807bdc21a5a0e1e7ef1fa7bd2f9449eda1bc9b86e8b4efe33221a436a864cb272db8a50ed3696634ae458566e562a1dbbdfb20126c3ecbcf403816fb49adb749f51a76acf93869101c81d8ab1292e4e528ff30e58d4ccb34369cdabf927349fb8ab49ad569eaf0212dcacda9e1ff85493e6852418c647a4697409427becf65fc0710ce9c15ea9d2e799b39674afcbf2097d9fa9f4b10a874435cdcf2137d177d764c21a7ebcc303417a5ed5b94d0a3ae4be16417ff79fe1ae01feefecc5cef9ca7ce8cbe1287178349b33c40b7e7f08ab913844cc223951957043b6feeb1f56015fe5a039ed8d3f07cd55d5981e9f6609f2506dca0426b16c7008f2b25a67aaa3543bb8610354eb214b58b836e74090c7a43a9b47b91fbbc00a1b78400a42a1122dbb21afbe299b619abeceec31b32195ed805dfe64588703d7b12387b55486b39d909ab0690684471564417de34ab2e02da4d3974cfc7e9e38304d220d0a827a3312d085195163fbb712cd0a21cb151165bd98b77978096c1e6f38a73368cf7707083fb107910ed091d659af6a4673f9a155c8a402bf1c07ed416fa18fb66d6ac92d8a4c2d4e422b135f79ead28bbe234f818892b76fba8ed61b186b3b2cd1c773795e91e923c06829fb969926290ae2fe7585534e71c0c58b3bc662d70d537dbf06da794401aa121b4dffa36e574dda73e743c6177cb87bd78d6e0f98b081188d14050ca3f49e330cd1765c467430d197ee509dd8a000168212c683c6c7f075706cdded9c5a9609a6496280c1978d48e845c9693832768c47d9b7d1650e927b694a74ba50f36b924073f71f51b795f7822475d5632b80155264dc892effd97f561c1670d2417d5e33e7d095a8e44d8b0fc57d9ec693d12c277ddf096fa00081b2df89c46b66521295c3428df80915fa7e8f10c0627fab4e5d145e9fb6628bbd7b7cecc4427e73c6b1242fa7cc9df2731ae2fba2f9ef0d11ebb4e718e0a9b8b73b7bd5d257d22bc255ec751d1b381fe080e6c9a3e1204a1123c461796272ddc3b41f8fdd444358323edd11fab1bc5eda2111963ea999d743e6968f158d430fcd9906c5096227b7e5f377d07b2165476faefcb2301c03ea6cde213f7e165913f41fec6753aca94c0f365f60828c9bb9bbccfe030420212e3b5258668ebf1e393c5a7418292d7c819acbd6dcf109233d455a6075001416647a8dcde5f6f8fc0b161b252c37", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 66, - "comment": "h_ones above the limit", - "msg": "9a01000000000000000000000000000000000000000000000000000000000000", - "sig": "4e4f39e0fa77c6d67f49c759b83a72c2289fe57fca50c143c9a831a8114d41edb4bfa0856c62be9f05fe4f3672fe01549277f8b0da08e940f9b7b9d3da74e07fb7cf8a953fcace4239609a492220cd8007966c4e6ca5e8b418663fb1ff486d3ef90333c470699b8abef54c3fd4a25aa34d44ae75c216dd2d3f017082fb01df0d5ca6a85b1181484205722ef118f03372d8dc119739303aca686159911e165a611a678170a5238dc9b5631df11f2bcf3f7e5e8750cb55454f25a8a6e3efaa3fc66c88ad5247397ab153af4bc014895d006307e9a92dbb4e9bf78993980c525f2313d188b0f55718da34e701607d7149eabc05d952c4e12a3516d8e9c1fde6eaca3cace1e76749b156c46f40265870b1ea2fc49d66b600a52beb187675d1b7d6c40445c678974625dbfccf20ca3b65eff29d7fc3033f3af4b2c29494f18515f378ab2f155b392da15dc1f65c7a37ea2bb2b69eb0f8f66a6507025811a2ce5f748ccf667f32b9ebdfa37b3f4a164534de8ca9bedeff425920d38b0514c62068b92024e014283ed633f1820d2851ccc8268a443349903cc70af04ddc4dcce2023b6c0ce625797972883469b38f7754b576595a97910ecb81d97c801be74e7b8e7eb902c42cba946d855cb9dda4c140d4ee37504dbed3ef92ca99572a7857f6383d9ebe3105c90e9cc196d5c259b869a8e8c092432be67cd7b873ea408d455231863c5f34e38fa194686efdb23b79b30b34998f031179fe8dece8e79023cd41f0e92e18fd815d7cdc69dd83d26ca7e850363c3369cfc8706daac31622fb7c419a37d4884edcc10eacf0c4442c2bb47473181d4cbd404ab63bf840676caecbc89cc17ce0d14849a022376ca0548ff552d229c92c05b48c299d258644ea7b6462ef6b5fe965f6129ad9db2e95eaa14e28866d7eca1c90bdc46bc8f0da5868243a0f5a2ff3f08baa067c03719da8a3bc6c1d14a871c7a630dd831911467e1e6f19ccf0a511378319976015d3a3167d2570a49c50fa8d17b1079f092727276a311fe9f0ebc005739d8733727273aa5267021dcdf629321364fcb46836209c54d8266dffb01abd69824245c9a7f6a706e1d5deb23a15330990ba1a8a7032d4efa4de64bbe9ad4bfafee9e23b62faf8ed88093f5459115fc3d2877028fea349285888f84c96a1fa415fd1da7e878496e910cc1037c0a482e65da9209f40ac89e92358374144d0cb729279ad80e28982617f5ade2dcf380be05709c0de1e0191cb873e35d98f7fe09b38fc2430778d44752749414bd554d1b0681e98fdbbf9bf437b9e0473eca06ccd7e0cb4948d9aac13ec245a850b0506c6127830c63a75685e430318365f4ff06dcbfb970626ef2dc27dea0b0a098b2fc5a0ea02fc67eb3a9696ece6c752fee088d8e71be6ebd94aace3c78a9113b8e10167da32230672a2c311f12553ffbab9436de67657725e96dd516c9b561c3b272fe889e8ff2811b44426d26a0c42c24349aa22f85ddc863d32ac91bea62f26afeb350c81439964388bbf21415226b368188e2adce8ecdabbb3e38b1fec29bb55728cd382b3bad0783356c739f343c39afe5a98512b3f1c10058c587c1bb729417c26c18617f96d2de956de1d91cae81e1eee0d2011b5706c3b07580eba78066aa2a812461fc967e04f283113c30f6ced3a237958ad71c9572c8d6ecaeda361171199953fd7bb73fed1588259870adb84744e825dc84613daebd982f4487b464f128c2a7ff49b259c991ce34a013f9374568fee8e357de35dfa5cb43542cdb297d4cd886e0605c3d1fddaba262ced5d1edf566cce3840ba338db4fba236ec926a2134fd127d40e3a84f6b158cc6ce48f238c078a795caa391e793716281c2936397a50cd417cdf9c7fb32b5a8b7690e2ae2768daee33fd33600ab6d1eda8c37bf086bd3c1be7a9a2d79ba6ef635f9321d8d03316a8dc85acb4ed7a39d7cb30a76c04c018fc9c3c4779a8a67e7975c7a45018f9f177575ade5984ff4f7b412a18f1c24402e9bbc5564ef98a920e00d4bcc9e307e854aee1a6a2f421f833da3d27b2e8a9ab7b9f1061faf105d13da2359e9d57f47fbfa56e49b372672de5b460f3c43e9d32a0e3a272fe3efd0dfa4740539be52d4ec7881d9c7915f8cda2b47dd520ab5c5ba8fac6b1888b65d1bf12c976051743d6a506a5d4c550262b23e4995cff4bd6dde88ded5fd49608e791ee74c2c62571daf881ea9e318f96447c0d6d3ebd42a1b4a448e66359db4cd875885f91f7cffbcda373af5c72c67c9e3e8e14b6e0f5d209980d4d9be3884878f7f97aebf74e86426bd8b1c11ee5df701eb47a86877dff6b7df3d343f8a3a24697294f15de1be9c20092ac2c53d2d4e9b8011a2628416ebdae96237fcfc980d69265b03b86e1bb6954ee19e4e7598b068d131510a4e13c38d2c763c32f6a270a50fbfdda0e50b6df49fc85d3b1012b374a1095479a8d330f6c4d46940854daa91d34ef96e33645a444fceee47bc7faa680a2365eabb0c7acbf73bb72364b865e587607e0f4e15162be599703e22f782b15686f32ae096ab178216abdc687310330082a057286235e97f0abfb5b00443acb5db755fde1c4d46a0ce5923d8f7b10b0c4cd66a887c12a02ddcc022e261cc3f6ec65f1d6b6182a19a2c15f412d0a364d01b5eef67f665d42a6087d798aa94581fae60cf86cb9aa90c6b9e63e3269d78eca3f269f382e69a3bf777a420ce56866aa82ca5c4131b34a7c2e4cc8c685368fe8df1ba500fc6f4149ba21311409f517332d54d10337c762e0806d66bbd9426805521dd4fadde9987708f7e5cba96e9afb256f729ac9705c8f9069f77b32f5609d553e1357fabd6afb3439f99ef4d23e1e4e65815ae079bcf0dc408d229fa63b44b50b1075ea4d414caf46654fc462a643b4ed38a037e9fa9cc56e492584a69681bdedb72a48dafea506b19e75724d54cefc666768a7b40c015dc055a8b058167965efdc7122b25807555d3b6e0137bb98b5e16a72f4ba873ebc32c036d2eb9092b64de62dd95526c4900bb64112bb0703783c416be33d3cdbbd441316d48226d63e69471845a7f5bd93ddffbb0bf9385221c3a9d80d89f2a6f6bb233f3d0c604854b86b79b1d4cbe50e76c276b58f25ca31e415e7b2dac266dc3b073f1d6b00d500e54981079d66a1f314653b733c6db19168ebef304e15760ef535b45012fa4ce3eb1ed610a5ceef680f8700c174ea474adbf45410df72ad777c72255b2e77e467453da217345354f3570050c178dba294a95c5bff31c95d24fc757d3ac354cb7d7c6892e8dfd9c0062f3d3071ef316c116511d78becb255d185c81f61c0e29ce521928ce3c83c9530d53c7c6c0535c9b384b090fab020d23c199430889db214a84cac3e06888fcf45f19ec74552e6f45380faad1380b9a7e5413d9c700c70c6ffd003f3b52f624e6b04948ea99b3fb129c2de24b47a91d910f35c24efb9f3d788827b74a566607846015e6148b4c76355b51bcdafafe1e5298ff01879b1e9ebd430681c8c82f194498e78fe3537c99888f11c063997ac36d1a00a38d51bf5a6101a2322f70dab430ea99d14ee833a0859d5bb0da477afe4aa3184e480b14e3f6a362ef3458da1ab5728994ed6c8899dd6e5a9c78b38f370fbc31661e37d402310a9dad865176486144c451aff71715378432604d9194ee88ea6f3b68dfa1b80b0a6c54a2b5cd4c0b4b1ec7152c680483b537313c4b6035cd550d0eca0df04d9a058dec727ad5675285fd1d07a4a7bf36a330ffe620a1b244583bd3b248be735bed76e4f1e47fd1f81d6ff3339be6d9fce2afc4ab2402f3d2a9907c10fe4207ffb0a3ee49a3ec7b3af256aa2d63d69b4dfe69898c858bd8de9ec4285f7de3320c18f669574d6cc9a08cc8ba745af8a5f0086621928a97d6c92103d34c229f6d8b1a36e8e2e86a8dd7ef4b039c1b9546f7ebdd5f179a94146fe3c9c695641bc51db41ff0b074f467bc07578fad564269c65337f6a0b8af6dc0f7640cc42fc8dde6fb7cf677ff7889ddab792fd225ae4c8995dc97afe843831e8d48f419879411f5152cc6e1d9c0624d8b1bd6a4b136d67074606ce5ee30b0136335526eaa352df9fced286530848115509e82a8a4a3d929a5a242415579d97995cdb20c737ce4e63e490860e58855d6574ffdceaeab8fbb6aeee1c73b7371b8d24dfa68c4e29c84a28bf78b2ed283c15248a13efdb4aca13e25f69594660e73dd847c7249d64dc2f1ec51e88c675fa2bd5b77957765e608c3e32dc991a14c68fd7e9bbf17e84b5dea7a2ba9414851a30994483e0e53ac614c72c5b5d0407c6b0dbbddebb4fc0d0c195237f9d2e4a11cd10f464b35dcf9bd90bdab7f1ce583477dbe31b0b5aec91ae86a2e0cde82261665c570f0c055f1391e60669e7e7905fb9bec5f0da2485bca04837e683fda337a302254f80ba295c96af0aa97f673efb3073b581399d76cb234296c9065f363a5e72484b7e93438055ab952fe2e55a23b34acd34957a682ed8f17b0a5778088c39a3dd8489823c8cdf588b73cf7c5010fb36c590c99fcf30cdeaea2f86fb8375aea46b60dacd83acb0b1517589f2c386069a3b6e4f81d445961646b90bfe6e9f6ff3f4653658d1e373b5ad41835848cc7df0000000000000000000000000000050d191e2329", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 67, - "comment": "high_bits called on the edge case", - "msg": "8803000000000000000000000000000000000000000000000000000000000000", - "sig": "93d46453ecb0ad7a3e0288445607fc4fc6704f17b64fecfbfc183de4cad5c86da5b1d6c13fbbd1c1f8a8818dccdd5b075f9470e83cfa231fa5b6036ee49ff80b0fb7655f4b7f84197027c868a4d8fdfffefe3317c336101c4749b465325b45dec08ff915e606e7cfbb5558e95ef29b194752f50d7a5b11a14d131b0c9af6dd154ba49200afb1bae5b9c0ac7fb0297c72281d8462dbc89cd5b0d66256bc942905c9a805fb14b8c4931550ebb70ee04174784cc02fc8e97b5dabe50583d433d11518079803c6d557a13187cd96c8e84e8801c11e2666596f055e788deb0a713862f2daef6e1acb60d83e39003417339b871d27877823493fd360b27336eab688a71d4b0bdea6641b0b0ea1ab65fd4291c380fc76a75dc7ca4e4711af22ab5be96a2e4f301f705ff033e3e8b530bd8194b9cad4f54680eaf9abf0be7af032a2766fc75396894b2f393b1b87af6d1b9730d374a5e48964bf1ec6276e6ba4554e2f6114c04a1489990c7901b28ac94de8c61ab983319374474a2aa8a0e1b5410fb952105a5cc0ec9b9cd7663e532bf787ed992726fef537e3bbe31ba835e0a0ef00398f7d88ac2ed3d59a99f9a6cd49fea68e3a611ed1600f738ee199d3db7ffda3c1873dc9a0b1ba9b8aa224cca56460965a9d6c91d58de6c33f9665df62f4be77d333c4d62b967386fae73830389c71a563ddf7172b68b1faac5fbe64e06b53efcd058d4a960364fd879eccb76a7674a813453cd48868b9fcaa96bcd5dc815ed688f5126557158bb35f2c6a0e4ff4c010a3afb6a4122cd3521c3d9e3c717c79c8062d3fc24d51b122d8a8714f9ffc07d4bd8d0e012d7ea9dbdb2427b0ee12d44367125e63a275d70b4f5ae5d088130358739cc31c3060ddf91c3cc64957c76d451cc028555abd5811fefa5a10633cb0d8aa47a8b6718ec44b1cdb06a35d6ddb332efdabca446dba302e2c7124303343eb42ee3bdecdb894c1768d1680cc98dd628067fb39cb7d67a00784995bf5ea3f8014193c7a371dcc55ba5a3b43d3f2a2228126856ea0d97c90b6081a45491c3c8e20f6dc2ffe331496cabc3619fe86e557228a7dca189e7a3cd04e961616643bdabf6ace94f3d5f1e8429d115b3b8c840245fbf48d0172b214c0386fd320dd1e2580d5f4e6cfa9d4928431633079a90f97258418ebfcdd0aab960239ea2be83b8a057b0548022bd518661b703835e91da0cb568a4101de68d5787e31e285c335e637f83eab3953ba292244286d61e06fcb961e319ac80d5173bcfe7128dad75e2e850085be27356495b28fdb55313d90c4807f6546231fce0cbaf1fc6419ba60695eec63cae97957baca1756630550ca14b56737a52de135eb711c0a1dec9e1811908ecf299198387b741f904967404f7f8ec9f6ebab878caa4b664cb24c53bba4607a7bd6e4c4db5f9c8d712cbab6a506d0902764bb44da35cc0f0663968b3cf5bf92f83724ce08d478a66ac0e430c42ec47ef4de4a46e7d047450e481e4d8468261315c10d5bbd1ee7ac82f0a63a9d4ba54f6e4a367de6b05a560482c8826121ccb90f68037a96c8c30e41f1a96c4d84c021dadf1315c3a6f80e6ef7d26b5e4e87f5436347169d63987c022353a8155670c5be558544ee3ffc3cdb717bbd53edca18e5ee0e5646482ed38f790aeb45bf89a40e819b14d535da8b12025ed710c2f2faedfa716970ee44798de2932946018b6d80715d6f6d7d573b003b576cbe2781ed12984a4171c00d5f12cbf7e73d567cb8d243544cbc5c7921b5a89c0aabcf1339f99671fbe96591f988a06f4bd15feae56429878e40ed8f1e0e90457f1ca21bccefaba6d30709f40508c47d78c72362d5d96a279406f10f975fe70872a4e214eaf3ec9ae5dc3b7bc41e27b72da8f6824c259534216577bf506ad45976e84ad4ed9d5a4f88e3695e2943adf045b91a5edea2410ebed5d2bf10170d3a0c392e72e970c715c0216b97ffc8fdc9089a9fe1e4f4cad9ec4e4e589fe05eb5ace4083805f2cf936bd93b6410138caff44c64be949fb7acc66284bdd8781417976f7be700bef0f78f1398fee069b14e686aa985aebdd058230b7684553f02a1e196ad8661759e45bcd1ab75f8d3ec95602ff03e6b314d8c363cb7c843df92a3a6a355e29a2ca881911b7e01b8e8c40f7395a5207650b0f44bf11b1269b8b0bd4b4c989c98ff0c529e0a3b5391ca25ec366e39fc6da4c474b3ff93938fa064b1a30a6aa56a717d5f5bed2b3cf3d2270819a8100b7fc8e750787acbdf008fcc4a0deaa47a62084c3445c75cd97edd1e4012b0b76b01bc1ca8e5738bf884c6135934304bf625eb8a3ccb29087047a0834943a6bebff481994779c7f6a37fa8140105e849696d922d3e7cce3535e9711422dc217f5e7f2c379d5dc8220a5006b56a87079b1504d6628999ee8158c73d2c101cebf695adb5c3815d9328255c5dc2efb167b36b1820abb79f0eaf4fd84580ff7c3a8b178164f985f42f0dcfb728fd42401a31a2ef2ebd9a26e6832623d7d28d26d162a21c45889253f62a11a2ed59414ff03c27e48aceae70ec4629462842626d7f802371fcd7fc1b97495e861c7391c773fcaa2ed087ae8b84968c573f091ba37097008d6041460986403e8e1d2e44ba3afa5cc88d48780aaceb142512b115d47d7e5f9358678c99d2f481d5740b327555ff41e163bc40b2021d441e5b4ca87b02010a454c6f2c9cd1970cd3846d4c8021ac7028b2e94b3a9af750e76ee37bf4f4ace83b244aaed8c1ba134500357b96f587bc1464cc2052b03634b772920da0cad300ad9de1f53c8b8c373b2e12b552c4410e2836f3161fb1b7c0116eb3fd23fd632fe6dbe2e9999a3994793b713d52c811403c3b9e0f5d9b68b71835e9dac66ab9437b64151115bf3a8af2fe17de721310b459ecabf6790096df03c23a8165cbfb484dc35e0e14ea64a82bc76b888f6bbce7d29741ec435aabec2b9ccea7b61197a895b608d88666c1ab1ec32424bacd2c51b0a248ab18e0192a866c7de1ed43ec7e7eeaf300ea40143af6be9d93bb92bd0ea5d9600f99276de5a23eda8f939ec173a141285b0323551137dba54c2a46fa5decf94158646edc72901fcdf86beba1a8715159f61ce58eaba2fd09afe8b533817086cdfb641f4ec3c079cc27257688d4b1a3dbfe0a0f53e74384e2b89c774ea215ab444a459b5f9ded9019f57aae07c44eaff21c7928ffcc621339badbfa93962630c713072c5efcf52a7f2d09d4f164d0b901d34c37dda11aac6b6a93f30339c786255b1e18ed055121a5b52b1a0afd76ac8d4a3b1e72516a8ccd39cd035c11f676ede7c87d932f1ef99d3b93a79e7edb1923de83498c94db1775e9560753f65a34df282ef215a18662f446e1a80a4a64380cb4991aa5ed8fd1fd24eaed4ec91536229596b765197c10943b4dfa30750728f9b7ec39b798e33572da27e8b2bdc5a596946e99963a1e164085cbce5529183159066411cbf62033b41b2c0f59a4d771b4aa9a82bf781a384a370b73b59c8d64450b8e75ecde8c7eec2ea52351711b88b7e462dd7069c2f3c00a0656cb3cb5cc9338e2dccf2e0698be77c19f85271642b09c41932a0a54f60df6093aa41ba66734f0c91d958f9798169b35697ba42db67d33b9151b3f176fbff73e73b4bcdd9f2b80234e20ca079a0694977e6e150d16dca677f1a195348942827ae2a32a7fbb891df99eb03651ce7168d8f26db3c6d71ce778fc0dfe75010eb80612908730672fd0344d99a85090e78e454cc7edc760cb49b672702d388689819f55a353bd8da92e17daa34097c1cbc4574a243efd2dc908ddab79d7cb33ee1cc7a0c3564ef545d100bb6ada9d26bbd306ec7b543e0bc2477d8a283823b65b6a91ead38867bf83ac3643be995b38897307cfdda549a9732b2c3ca88babb8dc9c3b59b208a596b57bbff42c586b97a0e55ad9025f6c421b19c1ec36b436398c413ae55d064a46e2b97a4d475170666f6bcb7d5bbdcc2a3d28be3e5a41abea942ae836487d7325af729116a3b009b47a1efdaa4142a054bcb672951087891aa3af203f0ed41efc9422753a7b07ecafe4d9022e7c73893621a648d7dda02181809d7a687301d156bd90c3e15e1a746b6ce93fa2bc2d8309b8135a95c0d12700da6eda1bac9ea1663446cba9e8237dd019d7e016ce0600c8f1cb435a8f4f52deb8295ce00a07d3a32456e44bc2128293295e550e816069979fc379da0a44d9116b7e6a1ffebb750f2d7f86a27d6d93cfc739efadab272c77a595f6f74318d14fb4e15ac8ce9fa0f7c72ab7720af4f3da27bff92ba62fd7fd79d96a25c2fab26034e3f331db56add047c8840933b53e06a0607bf3dcfa4fb3227dfc8a33a26ec9fe03ffaa538b6a8ed9a58df01f0b62cebd303f11e24fdd373ba23adb698c6745c41f57cfc465d10aed6b08f171acb42c5bdea41cba6fa8016ec7603591468d310746513a24f77155be87f507e7fe8512f2fc889af9ebb145d5c33137aa7e3dc9e14d3a81c2a5149418782e082745235c62969d19bbb349b550524102aed4c1d66a3a98f8646f6f0c0c506b64748c6747b1c1cbdbe815005a71cef21a1c324797a0e30413292e78bcc5cc548d99a2106b9ea6eaf000000000000000000000000000000000000000000000000000050c1415181e", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 68, - "comment": "low_bits called on the edge case", - "msg": "b502000000000000000000000000000000000000000000000000000000000000", - "sig": "fa54682a8226fa50a7728ee9ce8aa7b72bdd00a4f5643c4771d6547275088fa7b32042cb5441cfa8880779a602c32a536236b3be35a6e2a13360d4825d52f511252d6a3e272b493bc73878e0e3711360b5360af83df3f57570667d866c8558b052c540027a690df9eeea1135aa50546b2136d349cab85dcd698fbae1aa6fe0fb2eec20f3ac4f004a55be8510c4015f74538fe2e695cdc154887631dfe924774a6731b65aa4349fa16d536c7e9b5642966606e3fdb271779ffb0d3599bf958d3727fc443a6a190f4bb2f2853f5f6d773dbafc371772bb3d2b0e88aed601c9ce8ffd60b2496315f507bdbb50c7a309fcd68d85fee1f5aaa9420c4d2b52147d7fcb38026e21b5c467af3ed4b16038f2beab5f54b7c134571c079dbd28c54c6e06505d69b6dbae1e720e8a8bda189867861f84f5f6fa39f9af2cac8c6153bf1533b21f1e70360baa33860353eda4f0ec700c58283e2a3fcae5f0053c395be917ab411b8c2bfa94d892bc4fa424f6dfd97f9fa982b02e4fbe6c43b598eba769629ac66c3cde157365053fb6595982daaabae610cd3458811da53cfaadc053d8af104896e438d7bbdb025c474abc2493f74e16fa8ba563ee0765f4a06dbd874748302dd52df925df631e5bd5a7e335909aa7f8e7a65a7db7cd1988add9b9f34a71e3b735da6dccb4b6f6787af5f1e519e24a1e15c5930f43626f5ed734d4c442125896aba42840fe0613bbb8cb68325a6bb26bf1bcf14a055fcf63f11020ef7572de02b677315a6c83a2d0bceaf049e91bc715a085a25769ab9c9f4b6592a41c4c7e212c3380d723d3b4da5d9baaeabac9410e32eaa58f38facfe1f7438e4eec3ce5091a1e38f98100600dcc215d3c8ca850b46d60e2b941e10c66d809282f9d38d710a9202f9bd9a79a62cc30b32b5a1af6f9de111bee6a5bcb65e9125b8cfabb6db6c750c7553d6e3975be064feecd24e26c7196e931d8b1ce48ae6be3977db6d7eb200aae36191f7f0a2be3d3d7c9e760be49c8fb0b495338771f4b1676304c850db67d24422d7b153a4c34ca37a0ec287dd47739c2295dddd32e5809afbab880da22a82dbfd4c0041b0b8a6b9168e7baca62a6499fb621278ec25a81104eca44d2cd0165113fe6c68a56fc730ba9c7dffd039c978a701ed9f6acc61e39316ce53082c0dce04b4c0cb305aa53ac14befc5f65be4fa4bbdb79ab17c12698df9343de0b4cb3feb355cfca73529f36198d21da56bd343643a0d27d040f2bb7d048ecbfd1fc18b4bd27217c8532d63b47fedc445430caa18b2007ca9ae7fe9dae5bdb0371b897a3def628b0dddd3ba9b0805056caf5c02b7c3e44939b34ce646be0edc1289daa3aea0260643d34ebed8218aed531bee5ff772f2342e96e27ff488a5d1afddc3c5094a7f94f01c70ad619def58612f767cb21b3c742c43e94ff21b4f30348600a766e0f66d418b9f450e389be3ed10d3f080579248bbd7c72ee02985424c09c95b8af7229cc57e6dbd7bedc4aa2b08259db76736aa82bed4ab3198f748593189b0f5ddee1b1b8164f1f82896b458b6a5794170c056377b40e758c1d9f16a4b060f590d0299a3d6e8bb4d9046b194ea49051dba75771159d58d67d88eae6cd6d3cdab259d3b0422b1d1e0b40388d7007f73f3e1ff362c7bc785dbfbca4b4d007f3c799e8f4d11b806f26d82277f02ea2a61fa1cd5efac837aa29bdfa19cf00117f72b67c4df10a49a01efda625506de427d2ab9a514c9cf201ac86fc0692b66063aeb86b0b23e4180f6eb362b10a8dcd44f96983d5decb7b463882f7e0bc455c34998c65706e12c77416052bd36490796afdadf360ad94183907f807113b8c0533ff36b311ec6f8a31f1fe36f822ce27a580d2e5582a9c2991be1b43d0ff9c91447932ca726e57ab3ee076319eed5768decd05aa7ee857ec82b9132556cbe968f6ecc4013fbc49568c8c779d9a6d9dea52617e0f521c46d4862b47691038d9c36adcfe17a24a7f44fbd87114ef18bf1e1df13d15e060a01e2ff31c7b7ac4a355b0f5a3e98344d86c9510af6fdf934346e0b8c756fc5a14ee062d190ef7b6f78764e2063040bd09c4f7e43f1eb64f06d2e5c30b020d6c133dabaa9ebecad1623e3fa26bcfe1471471a6517de61f780b3082007676e5ff6ee9d5f31afa57c9faee333e639efc7761b0466f4c3b096cfda85d11700a4ec5db2deae29042dce8b74db1132104d9b9b0ef72962ddb6c23497bcc76e481871c322712ad44af7387a3e9498fe9a7c86ff73a012a2c5f0f492dc6766062cc296472f4ee671185892fd0704e8fb0c594eac2b817916ea7eda1822544a7ab2c2854e3b0c578fcf0d0b4ce731932af21a293e0c0e06fa5ba4b58dea2695fe4acd9fa6f7d1e59ec3657fc1f37e73e8e3536d7560bf502a103703cd815c9a10756da5d9e651234ff8d46f5f97bed85b89b6fb9c9c8026948d46dc5575679e8eb6cef8026aabb9a648fc87cc5e0fb06164cc22d6ab541caf5fbac8c6140d0fcb57719d45f22e055ad82b217cdb07dc986c4af4c847a8922be5d95f5367933b04b805e8626e73476a5da495bde018836ea5fe9cb34b3abe0b65885c83e918b5f5eebb53a962ac9e460dd6fa39795c68320e6b5f5e00638a1f18e40c3cdf75cc82794bf5f4a524081403894221f469efd48d460a8915721bcf0d6211949245cf7baa2f1ac65073409d9c1328e44142c9161ffc8d31ed8a387cf3dd0511cef2b61622de0d46d3639143339b9b6ed75cb5fa7c95011d878bac8b1be21be2e6608f040f76fe91f5b6fa92387aa081687da647712fa3b7b5e32ec2f5d22920acdfa5557ac8c071491bd4518c54f6d93bb8cde1a38f9dc1145af011c309c87c5b627690958fd466a4e8c073796f1cd07d844902e7e4eb56c031dd8c0dd6d9369c2eb4b89e4a9900bddc8114463c3ae2c87ddd1013b2defcf705ea746ff48d2821e5e63e033f4038cd842de7c838d9418c8e27a8dcd2fb9b88d8a0d0ba9c454d7a0a167a44cdc878f3274ebda260fe95a031c6d8917458d3882e11fc5363ccb034fca155ad29d622be4a047b3ccdffd362a3550c552a1b698e87dfba1774e527127017fdee76a91525993ff46b5eb072c79027148420fc958d1cc62e39dceb827dcd9baffcfc8b13888072827b0132cf943e31c71131e602444028740e6771a49615fcd00cf34ebf09bbbb2ab63b57803db54a1fd9c49957971d308548c94de5c5b6a5f345050ceb75708c8aee3c624e0d8290b2bcdcc918fbdcda7bc30d3f5f5ce1fb2d4e6cca86d6ec163f73858b84265baeeb0fda0f40e7bde058c85a2138bfa777c8be45da1c2b7915f94089074f4f22c0c1ecea9375ee2bfc23f90c521b8ed51434134abca11a9c3fd019244710125e9b7dc27661d23bcb4a40d5e87479d6b07ac86cfd91b5d89e664317336a2a6a80ee88b7b24ae1872bd99bd372d06cc21d835fd2336ea2ae53b7bf8a1c14ef724eba94e971524a1a290f9b7f265665b6195ee20719648b2a4a4a66c705705cf48b41a7c9c7f16bc2ae479ef1d5c23a4050acbdb0eef0a8c792f547952170a0b869f9b5066c06c4fe79d22379a5f8145c700049c4043215f60a7433955b2d9c681133149d845de27c355e1dc40217dae2c0a22c7d9b9e346ef585c35fd8cf96ebfcde2a7d4b7445e6c11046f0644ef7619e9c4bde19d33374061c7d55434249f4aaed4c7eb39a86f9d1007520d048301c9614943efbf9e55e11ea0b4462c9995c430ac4e7c3587df2a9f6d374580d0dbb48973c909615fb846705386c55d486063f8a0c9813419c9689317119ab6b7b6b9b72a2327bfe956859f8e3edd2d0e6a2e3446adb9c130fe0eab8dabaebd7593f9ca7b50df7c0f9643415b18f3c18ae06ec6ca1d39064b3bf8d8d4b841970e3c38c4e609fa7d6e8a938c371d7e4872ef88b088455715c5766126882cca88be8444a951b3984e1e24e38f87cc2d22dbb4459c258f7f6d9c4c70075061ab9c9a60fb23c0d4f5c9170c3368795acf27e099d9788d72e488742e04f779ac217f14eecbb4e3a41ee5d1b7e174b6df258ab1d8851c321c7ed74663e9f836ab08d8a5994ad7ea1be34ee3029b35550d653de0679b0d385315621282342dbda3abd445c695f67ba506ff9d4812a3a70996f26c45d71b9039ac4e4868047a396d838e3a625264e23178591cb966732901cf3960f0d83d4659b5ecf84e3948efde4413ae675d21a25e74aa780b3d4500b8ebb14898e9b8f332ea4524c7a560a630c049eb36b4ab1b4a77c9eb5755ff8a130786da3292383bc378ffedf2a7f3ddd8bdd5b7ff895608bc0c79ef3360c958d8e4854ac76dac7992bb69f6515052c47716a19bea1eaa0c0e33fa4f24207f7b44d5b48ed9ece05d5ca9d728b740e427823390c1d0d7998ce5edfd989c5d0ac351990cf8f291de748ddbcbda698052ee52cc078e15b7fb5360d890653c7b26458d0fdb813df3641f7f67613f5bd951d98128bff3a92d2b2c8b65adf282ff168af584730c3afdaeaa6550564655ad7700e5c34c6f74d091f1b367b210011788ababba86ba2e8eb6f2776c3e275637237c17250bbe31394a5a6f850c8ac1c9dbfa0f162b2c5e5f6e9cbbd7e2ecf72e7ec7d7f1f41b4d7b7c9fdcea4e6a85a100000000000000000000000000060c191f262a", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "f5408337d0fee65c28851226a5fa81b58464632c78e2a9bef70d330f2e3a5f74d9cf676aedd1067c91a5dd5d4edc46f868a93ffec9f44e254e44f682a153aeadf228e8db7c5fcfed30cc3408e261ab896876bee56660d2a7c1d7eac20c5754255206a178f7156295065ce7876f90c48f44bc37f3a00e32eefd3a4bb1e298fe283d106eaef92a33a594253a2a0790976a1d04636f8672d28c06c852ea8bb43b84bff512996e7616963d5b9a2906466a152c7ea9be178be35405683b44367af85d2daad87630c1e21ba5490154f0141780f5ed0407cb0b975dd56d5930f9b26413b843b83f3693304b0038bd3e4bb398868060ea18c9c67099376470a50deb052e4056743fbcdf0341b192663bd1c21ba3b3d5666e0d0e29c4e1ed0759ab0bd9d1d355011b94e0ff0c049b03ddb7138640667144fcacd7265f55a07e5387f1abd30c037cf14d436aa855f827049215440d8007f61460500d943f57ffb6bfee6fedd2fcec52882d7d8da1aab29e892c8beac3df3234b4a7d2eca3a45c6623c52bbdd07c1c94314b706988a52029f8f8b06e874b741d72926652c78c6ace2cfd8864eadb2e4b39cafe6e03e4edbafa2747db9bc42f92af8b031e3e380846b1bfd15ade88c285d6a6fffe91eafc8b17de6cbc68575f323cc09fc20e49e8efd76f9568bec486b78df4245428d8d0d5f53873e11de65fda4c770b521a8c67f5c51d48cc26358954514447881fd9a42e5891dac7e1db5249d7861b322111e5fb929bee9ff5e9d5a2667ba93e63fc03040d2e82648f89e89dec1d1d2dfb9efeceb7940f7dcbebeb5a239cc1c54d8f7d52cba220d0634e15df46a58280bc5a48840bd39274cfde150f9ad9a40f6398d715350925f0e0501944409f32331a362bdaaafb3d8ce71c964332d6afb7e684f99951246d88081c86744ae68133f22c53a4b5ae258f230a98491d2d43a79a6d0f4d54a3b62013965ac7c82d0507125a38a0277f81cbc1d46cef2a131c6f51b88ec0baae0c82a6a0e72831cb06f9116cff5111d597e01057d32805a008f52c9aec3311139bfb35982789ff83bdd0c31e9f1080e8ed8eb99fde66bafb29e3357389fe3785b60c78e229ef073e1b65e34d848bd4d8a4f251551e2d38d2546afbc205d3c6dab34d2b962b1afb44f1d22fc10c6744fcd6b636afd3cb414b16c2e0d708fe9f51ff19120bde693b028b6d1e6dbe37b4b8b3bc7c6f7a842701603869d3ded572500f085502efc8d3cc62b30e5cdbcb5e86d9c0d42973bf755df539cc0aea58f9148386db67bd2bf70cd12ccd96d5c66fb271416b772465228dc44b079178f9b766370b66a79b871faca246ca6f8f63be9f0668297ac446cad5cf4a83318b1b00ecbd283f0eecee60a9a37a27abdbdbe382e307970002837dfc0bd3934ebd008918fd4bd383c02c9d37f694996e989a49075767ebc4a2981ef5275455e026cb0bd70946cdd1fadaf251381d324f9efbb860d1b280c29685bab97d010676273b45cca12ac3966aae342c84e2357eccf252577743b8787967b40b07ef2d3d9e6c1a3bcb059cba0fdb7f0d4f815c242b8e14acd3375e608e9230ba3cf8718f43882a3e1e661a2bbe81830d34741f33473e263b3790abe67acf29f5df44865b2ffbc96975fd62738a64112deda5a2534fb0a23b3b3024df986391badf9041c593c313a7ca1e1fcffcb65b07b9a99337b4a4acf616cbe1553eb9541f38aa6247342905995233a28172ca13396b2a9662970120f82b92a213f43de7a232ccca3268265c9ce042d50915430a6c455f32277da42f9962fb9163b623231ebc080fa7b8e9f9021fcf85b98f9c483e4d2226b9326a5bcb2e7449ef029ae142d3a0f0c28bd4f7e9c51a12e1336f24dfacbc3f808a8f7dd683027bc948763b808fb0037394b8b41bc9b2ec7887e67584e03d11b15ca203b2bcb43f8881638c4e4eee7f846d09c7f89b7739df22b2c3acc235032ba8f7ae27b5b9d25733143e80a4cdde6770719c1e66ec2ce683612233e88fafff84c0745a98aa1254c8219c6c556348c2b5d1beeb61532d6bf7bde153271dc647460beb65fe0055b33fd6480dcbb9d7d471952cfa5be260c39721a8c5c89b9e966ae2dc9036451ec9f2c49433b2225e13f23e20c2bfba81a7b3a555883449238f7d48213e9f10ce19e76f1bdcfc73ee5524bd7d8be0a4b46784e238233c04fb99383ec7726f9717e1179dd14fba9ad6c2ebd1699f0ab0e57e6cad23875b029e89cfda06f51266ecd2eed4edafb51e82f2a506d57ba74da611774ca5fa2fff4a976519de425885e7d09219cf815b1767d4fc5a72c18918991a285086a6a766614a4d245387da50f28dd778fb33ab88c0918feba3768c55bb1f07aec33cfeed33d6faa4d34fd7227b365533c1e67dbc89f0b20195cf1cbd480d333ade1c9bb28308085b72ced430268c1492a27050c43668adc9cf8b8509447cfcd3c8f8d8eb554f704101786aa9ebca86991d250776a37a1f56fbf7d08e591f978da49c3870625879f70e2418aec5cba32fa8c346fa9038baebc35ad0068a4d03537aee14c2e71570a87490377fa8dd66f995aa044a522f0c7025a7ab2dd5ad30a64268dc112b7f9fa156df64d631f55f1d6edc55cec570a9c7372e29e02c8d4867bae249431dcf6ed2794a0183f0f7501201feca4a81d334c642fc8d38e9a90fa77429665e09e214797dfa455ff47c4f219d3a2cb0176bc2236455123c1c5da714ad29d580fb194f87173a18", - "tests": [ - { - "tcId": 69, - "comment": "short public key", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "IncorrectPublicKeyLength" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "f5408337d0fee65c28851226a5fa81b58464632c78e2a9bef70d330f2e3a5f74d9cf676aedd1067c91a5dd5d4edc46f868a93ffec9f44e254e44f682a153aeadf228e8db7c5fcfed30cc3408e261ab896876bee56660d2a7c1d7eac20c5754255206a178f7156295065ce7876f90c48f44bc37f3a00e32eefd3a4bb1e298fe283d106eaef92a33a594253a2a0790976a1d04636f8672d28c06c852ea8bb43b84bff512996e7616963d5b9a2906466a152c7ea9be178be35405683b44367af85d2daad87630c1e21ba5490154f0141780f5ed0407cb0b975dd56d5930f9b26413b843b83f3693304b0038bd3e4bb398868060ea18c9c67099376470a50deb052e4056743fbcdf0341b192663bd1c21ba3b3d5666e0d0e29c4e1ed0759ab0bd9d1d355011b94e0ff0c049b03ddb7138640667144fcacd7265f55a07e5387f1abd30c037cf14d436aa855f827049215440d8007f61460500d943f57ffb6bfee6fedd2fcec52882d7d8da1aab29e892c8beac3df3234b4a7d2eca3a45c6623c52bbdd07c1c94314b706988a52029f8f8b06e874b741d72926652c78c6ace2cfd8864eadb2e4b39cafe6e03e4edbafa2747db9bc42f92af8b031e3e380846b1bfd15ade88c285d6a6fffe91eafc8b17de6cbc68575f323cc09fc20e49e8efd76f9568bec486b78df4245428d8d0d5f53873e11de65fda4c770b521a8c67f5c51d48cc26358954514447881fd9a42e5891dac7e1db5249d7861b322111e5fb929bee9ff5e9d5a2667ba93e63fc03040d2e82648f89e89dec1d1d2dfb9efeceb7940f7dcbebeb5a239cc1c54d8f7d52cba220d0634e15df46a58280bc5a48840bd39274cfde150f9ad9a40f6398d715350925f0e0501944409f32331a362bdaaafb3d8ce71c964332d6afb7e684f99951246d88081c86744ae68133f22c53a4b5ae258f230a98491d2d43a79a6d0f4d54a3b62013965ac7c82d0507125a38a0277f81cbc1d46cef2a131c6f51b88ec0baae0c82a6a0e72831cb06f9116cff5111d597e01057d32805a008f52c9aec3311139bfb35982789ff83bdd0c31e9f1080e8ed8eb99fde66bafb29e3357389fe3785b60c78e229ef073e1b65e34d848bd4d8a4f251551e2d38d2546afbc205d3c6dab34d2b962b1afb44f1d22fc10c6744fcd6b636afd3cb414b16c2e0d708fe9f51ff19120bde693b028b6d1e6dbe37b4b8b3bc7c6f7a842701603869d3ded572500f085502efc8d3cc62b30e5cdbcb5e86d9c0d42973bf755df539cc0aea58f9148386db67bd2bf70cd12ccd96d5c66fb271416b772465228dc44b079178f9b766370b66a79b871faca246ca6f8f63be9f0668297ac446cad5cf4a83318b1b00ecbd283f0eecee60a9a37a27abdbdbe382e307970002837dfc0bd3934ebd008918fd4bd383c02c9d37f694996e989a49075767ebc4a2981ef5275455e026cb0bd70946cdd1fadaf251381d324f9efbb860d1b280c29685bab97d010676273b45cca12ac3966aae342c84e2357eccf252577743b8787967b40b07ef2d3d9e6c1a3bcb059cba0fdb7f0d4f815c242b8e14acd3375e608e9230ba3cf8718f43882a3e1e661a2bbe81830d34741f33473e263b3790abe67acf29f5df44865b2ffbc96975fd62738a64112deda5a2534fb0a23b3b3024df986391badf9041c593c313a7ca1e1fcffcb65b07b9a99337b4a4acf616cbe1553eb9541f38aa6247342905995233a28172ca13396b2a9662970120f82b92a213f43de7a232ccca3268265c9ce042d50915430a6c455f32277da42f9962fb9163b623231ebc080fa7b8e9f9021fcf85b98f9c483e4d2226b9326a5bcb2e7449ef029ae142d3a0f0c28bd4f7e9c51a12e1336f24dfacbc3f808a8f7dd683027bc948763b808fb0037394b8b41bc9b2ec7887e67584e03d11b15ca203b2bcb43f8881638c4e4eee7f846d09c7f89b7739df22b2c3acc235032ba8f7ae27b5b9d25733143e80a4cdde6770719c1e66ec2ce683612233e88fafff84c0745a98aa1254c8219c6c556348c2b5d1beeb61532d6bf7bde153271dc647460beb65fe0055b33fd6480dcbb9d7d471952cfa5be260c39721a8c5c89b9e966ae2dc9036451ec9f2c49433b2225e13f23e20c2bfba81a7b3a555883449238f7d48213e9f10ce19e76f1bdcfc73ee5524bd7d8be0a4b46784e238233c04fb99383ec7726f9717e1179dd14fba9ad6c2ebd1699f0ab0e57e6cad23875b029e89cfda06f51266ecd2eed4edafb51e82f2a506d57ba74da611774ca5fa2fff4a976519de425885e7d09219cf815b1767d4fc5a72c18918991a285086a6a766614a4d245387da50f28dd778fb33ab88c0918feba3768c55bb1f07aec33cfeed33d6faa4d34fd7227b365533c1e67dbc89f0b20195cf1cbd480d333ade1c9bb28308085b72ced430268c1492a27050c43668adc9cf8b8509447cfcd3c8f8d8eb554f704101786aa9ebca86991d250776a37a1f56fbf7d08e591f978da49c3870625879f70e2418aec5cba32fa8c346fa9038baebc35ad0068a4d03537aee14c2e71570a87490377fa8dd66f995aa044a522f0c7025a7ab2dd5ad30a64268dc112b7f9fa156df64d631f55f1d6edc55cec570a9c7372e29e02c8d4867bae249431dcf6ed2794a0183f0f7501201feca4a81d334c642fc8d38e9a90fa77429665e09e214797dfa455ff47c4f219d3a2cb0176bc2236455123c1c5da714ad29d580fb194f87173a18dc00", - "tests": [ - { - "tcId": 70, - "comment": "long public key", - "msg": "48656c6c6f20776f726c64", - "sig": "69da5aec6d5f58fbf29439c520bd68b966e3dd2ca633b68351c2862344713a1e9c086a44f9a870a3ccc14de62d6c12b278c354d7197c4d6d7f83d1422b29b250f5ee3fec118311d905e5db2b4b8b23b8d542202d6652f6dc3f9d7ed51f2463082d3f145cfd0fa7ac548a47e91c1ccb1a55b215e90ab355bfc6d67154287b1dfae0fb530264dbb841a7684b396e5ca0459d795216416a9d232bc89b32e0f9461f53107c78e66c8e876554e8ddd501867b55dcfc1fb33f102e03373cdd192640f1027a08ce277b468f6ed0fe80a9d6cd2d6b2f7a3738c8325d95b0ccc6e7b9fb000c923b92298e0867d4a9f6dd5513e8001033c633bb1641ee66349487224dd43386c7fcc29916332066a868100d46e2c5b8354c28f087a024cba27694afc4c1665e0d72b37686919ad55052cc63a144febe4e2a0c9ae416e064e289f9f69cbb883665d1130826b7b74e30c94a2b98b67b471663e3d66326db3b43bebf958e8665b68eda90e8c5d9494b0c7c9ec48800910dd6d906b1fcd47a0aac462ac87b126d21b5ba150df61f752257ddf5a063b4a5b150371d625535e3b2874b9fe548960ff67931cd6c12496e8213e2ace6fff48e6bdc60310e49389f62579db26b92ad73e9d3f23942cab51784f48b3660b6450caecbb0df2aa4c8e56577f5ea450d2f7f51aacc0b304a62250bf2cae7b99dcd955b6596625d06da1c67f730b706fdba630f00fd891830d251484640b7258ab364d6fd9986878fffa69b7c44b92e43143affae8b098e1d27716850f37553bf266cdfb561abbcdbfeb80752b364434e64b80429b54cc88693ce03dc0fa147f0741b215f0728499bdc25140aafc976ac99e910ba8a8a50d21b7bddaa28626b3b90a93fd44077068357c81d36e735eda4362930adead4951a0baa104f384fc70e842a9f329e1868b07b455e9cc3fecd54805c9052e70f88c3b92fe0fc6a4d7dda18cf5694e5398860e439a1e19d5a66f2fbc0aacdd1a498711bb16054796c015a715395ef6174e37b04eda589b673c4d5dda737817fb52f392caf7a72d7a3e84b2180cb5b75bc8af065bdc05c3e4040435a1b160081352ac43e09cbf2ead6e09c2b0be0e37894888fe2812f68806f957c13fce6ff167bcee21d4f412ec95a4847f3db7bf441223a4d4ca9ed69adb4de8a4b5b01c775f2721226e6c59ff26fc38e1bb78a384b30e7b55f082e264d8f25e31518619ddd6b6a9faf8aa6cdb5eab75ed59a33825d5ef8b93bde5d120ada773fcc0852b918f4f03e2d2a543b15363adb823eb1f6c533b98d940411e1f5c1cf521f9f63d5454697608326625fffe01bf87f44187dad631df2898effd2c291d98222e564abe3b042b75e90c9c54667842fa8ebb68a1244bf8e0c3ae3ee5f97d5ddeefd986c4bd3f99d877c2cc2381a89abdc61713d38cee58bf69805a485c288d21b15843147066b4a74c69dc25de878e21d35fdfe6746feb4c166606bf3219e42cf63581e7e6bd6570f40f8fae590cedf5106fe57037ccb2324b74fca6500f6ed3d0736cdcc67d04f8fa9e80054a5bd7c8459fc1abb1c4c78677d7f6b325af94a0e5c9c7db0a748e12c5265e8724947d9b5c4bab1a8b6faec827cc41ec115ef3c2d7348cddabddfbc8436f3b41765e13f3762b3b45ed23156f085831e726a55d4b83848b3d1d3352aab9edcc0ac2388f2383f6301ad813b917ee3f23734e057832ae4cf65e668c9ddd0bdd0f9d8b6693254649668aa91a1fa5eb7c59859bb6ddd36c25f4a2223f5d688b480d0388fa307ea69298f9bf7737f6b3dbfda87b331affd75cd8d88f0460e98ebc2890b217bd6d11000a3a088cd837f4f8859a43f76afaaab05a0c3007a149d4d6b9155cadc2c9b55003efdec5012b6272b87183694c505f0446ede55f35b8ab201f9eda974ff840eccb0f004fa3acf753acd0613f66e2a6ac82e322199d37b4af83cbb3d98371c31be79bb42331e819644cbad2ce27a04e4c517998692cd8331552892e199a01a6922bda4d38ac4c01f708809e529c3216eaab399ef25b350ea213ba47126f278140e17391ca7139bd13c56f415e6b74aed8dbfbf38c95dc6db366fd72aa863a27fa1ebf198716400b978a3709e35039731930406588ebdffd35fa230a9b75fce41d7acd214ca4f0029896c137495eade0cf4d10fe621c73f01061acb077de72177ff5dbc6f0c5bec681aa34668ca4fcdd727525068b0b0e9072971b84ef6ce11d5c3c6024da40966703dcc2b33ae04f677677635a55db508f34f1403cdbe37960c8577dac3d848b29f3b5c5c6c56fb74f34c8f4634c04b8cce9b218f1760ca00e6de87efd14087c633469c892bf3e319443336733bb60cfb44941bfa25229aa24384d812db90fe74e0f93fda005eea87400736cabc036f71421b6657b1674d4a8f76cbbf3a8b1c0af82f72973927752257c532db439d96762ad64f102551a9d03f9ce3d8cc850c393c128bf8054bb55bb92ea31ec0706f083a9cf90424c617f8ad2a21225d1913c30e8f47a6b7131304d536a85596ebfd987b64b6bf3c51638d6c839214b53c3c10aa52bd9c6eb77fcf80b5e3b724dec1381d0e02207a6adc73ff53d9d1ffcee1c4a28fa5445ce518eee937074ff7a402f5bbcb362ff090415f9dbd93b62ee56dc8c50e4d2e34c6c621650c0dffe311484e95d68de77170c909c815828946aeeec7ede56bcf433e22fc63a33f764ced1f9242f3d26dc7558686e471f30fbe9304d3d56af8b23e72a4088970b24b2f7e968c1d0392eeeb0b0f0ac8c176547a5383d948ed15484b79e21314a1f28ed624f61e5aaecf2269e5b027e1910ffddede52fad4e8da224e8a10b079548fa7cd44172f4991adfd7623d13e5a19c812824bcf990c07c9721ded9093be6ce7bc7da3ac8c932133a64396b822be92b088844991596df893625a4ef24543bf75a10d7d17ff70350ef62ce3a7758aebbf9b3977b08becb9ea28376082f607965f2cded28bbdb39dab7e00833b0488370d221742b66e27d9ee2d9dd07f401bc22a62c8a9d8d3a290c63804991496aafa47a32578f583cfb53d0c2199055973440d7535e0da6cb2957f4e04002ecea68f9c3ff76cade27ed15fd7835989d0abb197fe32f68636139a42710644bb25860ff33f539200e3ccb8a7738422ca0fa0c744b4c19d15c5d4a3cb082e20a78e20b5a4965b043595cbcacad500b5adbb6cd597e6a4b9c5ea6a1f2e653b5474da277f1818048094ac9e0e1e0b20068d1c1ce5a114a4db7195057a6ce4d221c336fdc29190fee8ff855cae8b7f7c02eec21f972c827066d9c6dcc4a4179bc44ea9b88abe5124bf78b071e09e9af43f739a6e1030091fc091e73edc447f25c68bf84b8df7aa8f091ab42662b93e02c27003afc7b0ca69efcfa60bd53d4d78ceb7c4d2c8fd5ed7e8b35024de849e06400ad145fdb28348d22b317ccec704c401f88db1af2a5348223f5cefd914e404c9d73805d0de77211881486f1bf4aadacadd3ae2588f0db7b5e6957fed50a374f541cfe5e4e923c82ec47e5b3d2c70ad6760c79cd5080b490bdc75f9ef5e1d17f0978b1e8770775f902b9463e6980e1683b2454751ba2dad4a2e6460924bd60ff49b03230cb11fcd04a0388e60874c35d3f6cfc4dd487665e1b16578751eaea89e126bf58044596e3188c7a9631017be1f2dcd7d612331832ff8755460dc496aa99a61ea053c78e72607a18213ff9ef4bb880903b91e9a43e0b1f0ed1511b2eca2f4253fcfbd7d0faebf3680fbf0a45df231544882c9c46505c726d56905d02fd046c1652d8fd06d15286a1a8f8b69fbd825ca421fd80f5e9ba1a23f924937ad049adeec60c78fea1adf9b1ef7e8ac4d1ded18f1a801b0bda8fe9a88098825ff3eef5c1fc68cbea143310b39543293f3f5fbcf4773b02054c0bc79f00554947c7604b36389c0c45f597a88f3713456b4cfd83b30cb6520b624aa09c812066a8cd542dc67e19e4c92b562b4e0f6799fe57d9d4f4f3e0b6fabff4b1fc190bf1e78775ebcbe3655d370ca6c08f48decf6153a4989eeab6921f8475f85197f51d651e563994257df57977e5f219b4879751de57ab0374b407a21adb4ba520bb35e7b7508675bf49f4e432190451423cbd529fc79b22baae9cb1d8660c3a49c456ac03bc06c0ef3b02f7d8acd40919315206fb38e715139c9bd6f89a58634fe683df03f5bda719764f6c38131bc5ba1c53244472ef73834ade04b86ca08dd753141ac0a9a230e246735060a044018bc9b75d50134b20e6219c13f8325b5a0201e9453f6f012fe72e829ee1c637fe30037a9212a31c6e713726a6cd4cf2dd66ffdba77f1e2800e717940f231d04aa2e4e88dea084754947d848c0271856bfe659922408449858a81fa6583f062d96898d18ec53664f0067eb9b9c40ad2579ba9802abd8d1bf287e49d94ae397e784db14b5f7010ee4fc42e6e3c8ba80370afc188fcecaf466ea830d7b16362e5c9329980b981decc7174f3ff70a35d8a180ee12ed0cbffd4e8d14eb503387e4959f702d4293109e922eb561371f9ab21475821f8555d92f0aa1c3d841a6f1eabd4e663993636c754ce2b3c3f6a6b6d0b161e777b8296d7dce7fd162970496494d4f60716244a5a7fb7cee40e1d565e6566697e8f9300000000000000000000000005101318212b", - "result": "invalid", - "flags": [ - "IncorrectPublicKeyLength" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "5a04d37a8c83d373ba07da5cf96806002e3635ad8add42ce6ee9902dfc9a1f27cd931f803c2103d181ee5228549e4f2bb5cb4bfcffcca966f1ede24a9958ad53842a15db226adf91810a689f440ef71184a2c6b4f40e5f133bde58fe9331defa1aabb9819abdf9cbac8cc564ecb89d648cb5d66a09453da4dba410784fbc41db6216e19856de2bed90f6c30f3975a9b7bb47c2cb63e0b3df09331dbfbbc23c15a45844ece88226fda9071185fabc073a8e832e7a940877972734ca3bc6bd66bcc84a61b683a3e59c9453bb1ae493ea1f0988c30e05dbd65e8824e73d7b335465e119f7b5cb640725121565c5610f7470ab86fdcc18bb005eab35929df14652a9771a496ec4d44ab84688f9481bdbbf79614e8c4fc611e1086bf2d4c798174039dd9686aa9f43e4cbaf94f9ec0533465d327e758f99637600455f5a51e9cf4220e8cada21dc8a5c650cfb00d964c49575306862c7fa4128e6c65503f93cd3d2c079b7ce193da9c9577cd7deeda0f66c087180ecb7d561309cc1a2a9e9da2093ff5cf1f8bc15f1d1d91f6462eae7a9122234e660b1739b7db3043b09a1bfe0af241eb0249efd1f3255d7bda8749bc0fa6c193b52cb8b1d3e1b4eed21d7d7bd6f024c680aadadacf51b5f0bccb09735594f176242cc95fa4f61ce884b73f0878dbed24062e219ffef82a912435b55f954e58728c79be21cec1bd74b0bd80f5fd0a5cc418c8c936f2be63bcdd3902a0a4bbde4325478fd58bfae7b5dd977139fb7dda993adc68dad65208bef03fb2a20f18ae37344a2a858dfb47b2db4c24488650d19f4aaabb43fa8b98f1bee7a4d7fc38363bc9711d63c691feabcf95336c67e2ccca3f927641ab8d9b97f709e96553ec1a4948503b4783054c9d827756bf7cb8cb74b1dd5077330b2c2ca7460de521a591bbb8dad8575278e62b9129add32f30165caf72c05788773cfd4d7fc6042a72df403c396d496b17893a9694e0a067bb4d625e409ad5f0e818a81f314694e6c3eb63f0c7f468511462497eb40fa7a09d0d60e5d4bca7904de88a3b9b3df40fd4854142302481fa7458d59dbc295db173e1bec6e7c9fc6f1c46a4c469b63b286defbd30e1af010ae36c9cb50ba5e201d7fc5cc5386eaefca0d81c22f49a7ad8ecc272141e58e90d6e88c228c9c0d3c0947e13daffd477a055f4777761d060fe2505c8de34ccc96a3147619d424650d6230840c3bdb1a86db1d0969e1f5db8b98a8a328c9c2ffc0c90732845ac67efd45e29d7f5335637683a019c67b323e0ecb627333568a6611cd193eed5d12eff8528ed26a37fe8f0ea7ed3b65f434d69d4aec0b1f4a2ce9d44fc111d9e5a6c99f346379beea4ba3b5223eab08dda2841086d6974e1c638b82d5fea7bc85c0eb697c76265d147637e919725bc00ecbc66163a8c589d07d26a61c781eeb47189b993d5fc31876242c79b2943a4aad36933d576c21ad62596941fc9bd4fddf223f646858a726d489a0d89ac38f609092660fcb9bba8b00bfece9a1c2fd7d5cfcb3ed46b75a7d5f5f89694c76ef76443e37d0cf4e1bc34f18d8faacfae991f2d10e06cf46ca7fb40ebc4f849b1c6c7d9f33ccdbe9171c59b48b6be2c18923bbf33ad0101ed73af20150885dffc2f7607b1039d4a020a597acb7ebdff1b591ef32c213d8b5c67c593e91e6c123f82bd3f55c5fac30ed7c01bbd137adf7a1dd49c4338235da356eb6f4a4138626a832d2bdf590a15a98258dc283bde285d12c1bb96e4c664c720f8b04a21f70b70c6dda30402b8995df99f72d987b7725ab4426dd9a04473c7079aada56547e9b275626744ef69c2f867752e0a9fd18dc6ddbc6be74bc42e23235e8d12a66de855046c6dfcd4e89b34dcd0d1eb1b0836b74431e8c7154b14f6077dc6baf602f86afbdc0dbe1c1faf81efd83b7361ffa9d46449b2a10a040b1857cddd5f274de67559006fab88536365f63ff9109994d395baba2410e613548528311ba3b300b20ea1b29a333ae40c6e77f30d2e0b2cbc47ffd849028189489c580aba2f2bb9add957a4b3257e3740e81515930419b28aa91df5ffac928857830e20a3ae970ddfc8b277f656d117cef643dea29ad1479c1d9d5f5296011aa5cee51dd4440a770306a561927b52fad013801252a9714706e3d7aa198119467bd5f0f4fc1a76a5a727b0dab83de31b4581858be975072809cb1f7e56bba1dde4af1122b5a28162bf29fab7d4a864352af1699f3456f4d7bd72752d477ef16fe44bca379259f6562fdb8821e8bed4772b3870397474929f5354c360b06741a9e2ff7f62e3765a1ac1eb69507ca0682282562744650769798b91b92f7b7b6e251c1d590aeb4c69154f262d3bbbf32653cc1ee51274ef7137d87c5d71a7cb4db570b1fc0f98627aa025a3cae57756ffeb5e2ca0dfc2cebee981e395166470ec1feb9705a78ccaaee282d3ba43073f9f4aa8026b581c2555f2a77467e0f4d9d25ed02d59e1e2d6968442bb737ead64e377cadc229dc70303d5d0e30bcc620dd22736f4674444b54ce16658058419bbbdd2b75937df077b2bb131ec9cacecb6720b97aff8907785d50d48d6896c54b262fc114d34421d3e210e4a393a357011eecb39a877fb2b65da40638be4cc434a35b3b215e3fb673a302656c96a49d6d007c1708fcda4c2d1e1699969835d8427c1b34b14660c2549df232246d729bd75327458895df9395f06d6c8f817f9b6ff38c48df0c0378c035cdc3a3cc9a8df239597359", - "tests": [ - { - "tcId": 71, - "comment": "private key with s1 vector out of range", - "msg": "48656c6c6f20776f726c64", - "sig": "643624d994e78995f463e4fef0589a691f9eeabada4672ab948204776e6f973053461e5e5d506bc427aa31aae371805f0b558002cfab1174da48fa457204d4be9e7c4a5cef4f2a3d12ca5baa45ab91020a01455b1426fd3651f8d82ad270929fd2ee597b313a663c553f283089c1d4a068bc8f1a72f518f2ae5e0e33531da37eeb83810adf0f407ef09df510319c8dd3efedf52e59dcaea158792a58420b373acc2247e4710b2e7e3d17faf81333afcb5608a0cc5803fab5ee1533fd63724cd1782aecfca3b090dc61907ec71220f20758f1edccf7eec6ba904ab241b151302b1cac2c0aa87dbe8290320604afe1fee787e5db72dce3813720da68758541d2d2e98db1719b4470a7a8924b91fa590701fc3f9b74b56d608aab2749a270a3361a6b7e514f3520b35cd7b973a759aa8626431305dcad6926a8d835ae9ced34557773c90f293ad98cf0894c23039c0b3dbad65b626cb8b7534c89e8a60355d135a35fff6d00d6ce34ffb846fe02bdefc7d9c2dea6148eff121a964d1eba401d2e32fbd68c3eeac48a9c13700693c1b6ace46fcccf3f467b7d2eacb49b62778ca28df4857918aae2c0e38199394a7b4cf0c19dc10c6a5e4807245f057d50471ca585eb8369fc463123d5daee37ffd2bdf33e01fa5220c92e205fecb89cccd17492d62c0665580084c4197517ffde7799b3646a405ad243bb40ef1b11baf105f33245ab4e8844e792dd69c67119cf865d158eb90836bbd86cf336b33b62ffea13bbce0403e444d4bedc25d65b9e32ab3982fd9b8a2417c8bd76ce284df061b4db54e840f28035e1b7bf94e42a2cb097ba8a0d4eea197596ba6e8ea78613a23044c07ab602d6cba7978a120deaa6aa6de89dcac525b8ce47279138e21255a9f46a4b97888093ed9c7a6849bf6ff7ce6192b381557ef3e44f809e724ddfa502ac7c9e6154424ccfd60d8cbd2c43eb811d042a7e504ba8a426091319754327e45decd1278889e206a9002e4a45d54fa40e512c216c09d9348337b1ff64dbcf03d974bc1f15f036768e93c6281b14d1e8198f85fd812d421766d19bba569f335955a058b35a557157e82a1a3062e76686397c26279860417c2441852653b3b9304db38acda6814d12a6dc88b307d0d055e68f6ca2bb094e9aa22f2ce792da36ef0cbe0d04e7d8c76bd49fdb4a0faea798632f0c28349ff707956b40fd7944a09d18e2636b1e2bb9d8411fc450547775d218002cd7514e871d76adae54242c0f62423142fcd88f7e82572b38393357458cb36a8f6a2a0daab1b593f4b806e79c315144d4c526c7ca44c3876054bdbe81d9ea50ffdcc55b4e8b73e44b7c01c378183b1a638deeeae46003abc4db3a55fe04bbcee3366dd61b8461d286844c8468b8260d501307537f8484988c8cf8f167d85b288e89f21ba0e0b4fafdf94ac58227c3fa5a921f751afe981c5fe48e26fe780adffd6c4ffbe6609d0a822040e90a3d5ee047dd5cf86b2a80f117c9316f32535bbba7977969b07034d61db21ab76b87953d96d0c015347e797b68f5f912c6af0d2ac0a7662d1d1ec5e3a0bd0257730f2729c142e4eb98f4bc6ce4873420222c01020cbda19865ec27577aa9febd400854fc13eaa514284f8a5a5e8e3e3d1a3dd41990b58e1eecb7c2d09d502c23bed2025e06fee4bfdb05d7c73cc4e447aea9a98d90dfe72325daedbd989fe96f27c8ed3d10af771c12d84e488cc52788eb68adbfe35259135c12afe96f4a97d0e30bce518f25ab8e1f5296d7998406799bddd01dffd05247f2a6f565b1609a15f9cd3d1feda69e4842379ae3b0d705d88c0f47613c10825a145f5d8da8e527b3a4ce3caf9dc3b3559b7955923288443f31b164ac6058ab228ed19d73ab2dc870497969648071d78838ac13aaf43e50a6a5a83eeda8df974a56ec134ac37a805d3939b55a3211f89e0a0f963498cb6bb44f9f897a9c7b686a05f813c06416c923be169e7ac2fa2d12633142d2d5f52d8655fa76e1d7dcc63b1fbe97ddd65b886ce3850480521d36f8f308f5a4eff5ad242374304d238dbedc8b13f2ef5ef6bba9c818733be44f023d27f79dbfa76a0eb4e20304de0c7a1f38f705ff6d5a9e6a1076d0d3cc9f83516bdfd9dcf5537597139a26301d643f700ffe4834f4f449b5909862e25b60baf5941fcd9e264d9243e38aa813149e752e167a305b7eeb24caf0784baeac299f23578f2af1d85caf05fe088f98e1504cfe3f551e1ee47a3fbe30cbafa7ff7c141a186e43a1a52589a92f7584dc1fe45174a1b225466ba847cfbb47d55d9c5fe7a16f4106c4deade55d6c63f7b3ca58172d79b849874cf5e2c7f325effb2e4a632bcfd56a06b038cfd46a96949768a1d684a3ff660f2f8d252fb3e1a6fbefe7a7b765fdda9287b595061a5afec72e27d054849e0c905f8178b82b7e7028b2c9061b2c0a9a8d1137fa8bb0b5a823c5c88201efc49855fc2a96a49035b59d17233eff0f6b574933da9a6d4d179e7da108b82c3e527b492a0c3545f945ff495d9ce71fa5fe9b7b44cbbfceffd7948eb7f3c14b5047357572f9c7a39c8490f79448fbeb7f9e50f0b38b064a19230e1a94ec7aceaa1012d721a7fa9d940647f801c584f3a5cd4c2c3f65f647e9db9ae3db508565af32aea6800731873a33775034acf26b6dbc8c449a360a79d10d2186ffab29ff5d2937bf0f1c2efdb70327ee1ff901f54316ea08898310fbb8a94e6a8fccfafbf73394a782419b2838a2ecd53f16ebde96d70b1fd3255ee14586a63f5aa5f42b56b5e771ac6b2701238380b5427bd98a9bde7383e72eb34b257edaa669ae35a01f022cf0a96967e90ef23c72f2ec3e5cec48d120298d5a2ea259133806c5c7c2a53dcc6aa2c102c0ab3845a5785d63de6e58d240fabdd813155047dd55b3e0a8e0315eb427a83a4b754ca5a53b235b38df8acf537b1f67d52aa5d33e7f57ebbb89f524f30245362bd90f12c2e6110d19dd20864f9095e544b0be72c70d4d1053c7ae48e4fe5c4f651c18ecf5e51d68e2da2da6bbbf33fb1aa3942ed616deda75a03f8bc4128342fa1f4f07cdc6fb9c62e3a12bee90ffe5163153eae878ff1d35db72f7c74bc6f85701b4886a546d435e5fe10c7c1be65769ac5b2bc7f0aaec6e81957cbde411d18d7a0ff834d107507790856c148e564875c2bfad46fc9ee3b948636169b85f132e4434e994262ce124636507cf03bac88ae261da6443ab1f92ececeaedd41f9a418ade3b4a33d0d44af62b80b461007cb5d31e7ab254a8ad9de7a10b0894d2d47f94fb579bd775ee2b3b4fae126bb5af0a645eb80afae8631eeb06822a54bed367aebba0d29e8efbecfd9722ea55ba9ace571b0df38376c79deede6ed64aa5febbfcf865d4b2db00b1481235bf3730745405d4982ad27353eb00a506ac11c5dbefb7ab1b86aa99b451d81672990a8a5edef63aa9d1f124026e45cf6fb38bc4053bc7fd0de1ff8ec88f3fb8891e784560f9af15f64cee69a79aee5f180f498a0cb6a69eea5565eb97cbc64089403e45cf2c031af3d442774f048c9ff04e3a84693b20915bafdce5fb7a0156c5b58d157b8f8e68d70aa1d0cac1f78ec91c8f32bfcb25cc36001ef5d4bf18701e624a1e370a7ee2ef4bb5675a7ab4c6d148e6dd662364ed7f54fd2a4acb54568ff957f385290a6a34d3f80ca3f876b345da99ffa98effd361f20782111801320b1909ee32ad849c653255ed418ff721be631bf3af40c01ac90c0f92578fe22c8bb201db26dcb62f02b916d3a294ba4a4c272f26e2996649e6e7275a664e0810561e5b25e27abc703a591c9fb2038d4293da0163849b505c39b3d6b4862dbc393bc9c7420badfd530182a2b96260e75bdfa43b6423d2443b0ff036c468c5cb2ddc7db532d11541a5f6f132e98b0ce08097839aa192afe99f19e261a796ed8c123a02a0b26ba2963bd42c555876fef5800e0f08ae33539eca9d997e450ba040399971fdc18c7340ba6f691e6722475e71e92dc6490a3420a879e702a69cef3a3b5d49a6dfd4d7ece7b9368a169e9125e1eae1cb1cad85c3d8c70e264d2fe890f40af05805f3f3feff60858b155847a8cde0b5c8b3f40d8b22c3ee77c66f02fe55a67536a463418d393818f6cba0cb19ce36a42f37253d9d801f34a010a3a20f1113a1e7bc108c2fee2c97d03661bdff5b74402a35fe563d16fdf66dd4bd741381e7dc810224668bdfc480e62d25836dbd41b7ccc1ab56325b2a8c216246368369c228a42b7cc1c2baf4c021dba8ae8e4cd212f21b6b74d3279e2b444bc2ee6951995b9b069a78cd9136288a51d56f2406024d144f1acfb4828aa6e848ff0bba1eaa73a4a820e616320543299d165a7d4de422da83878ca1726d0b588a0096de21d895536cf13fe5714ded541399389d61471c03588c75d9f8928b1d379dee9153ab0fe431cce09a37d93a4d4008ee7da908bfe3a229130d96fb98be4c5b30abbdae2a162182d3215a8cd6f1ddd2741fa1ce51185d415d17686aace306027430d89ad80a18534a614142d6fa355e73001eb8938922ea54f57cb5d5449d076974a80c99e79a5b196e2a9b635a9271255f6c7f818bfa1c323d4a99f9acc4dbe4eaf412196ed7f70e42586370cccdd9fd0b1830499ec0c6000000000000000000000000000000070d13182128", - "result": "valid", - "flags": [ - "ValidSignature", - "InvalidPrivateKey" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "5a04d37a8c83d373ba07da5cf96806002e3635ad8add42ce6ee9902dfc9a1f27af2b332e1a44672f757802793a43b7e9f1927fdf4b89b7a4ad975ecf8bdaea48583cafbaf30c7ee6f668c225ddc25ba1d394d920f435173ea8453bc83bac373e3b6429f48a01c7deffc3ee5a986648a40dfcb31662f46f3a07d22ce9d486a0be0e822c1c75ea58965b9167ee08c9e6b07e80be89b257be37a57d5385a8bbf5e4439bf3aa80c17874a9f37d7a62eb0baeee9893be6e0fc223c31834baebedbd9611225d25542d78fb659b6f41ff3182d94b3e471f8c837f82a42fcab82ab6254a67632edf81f6feb720dbcdaf92c92a05f68db7fd074349cc54b84865326e3dc45e40645c95b41908aa66d38dafdbc4ec559cf0f86c5bfe7c2a84e8e56ac5bf97e88456f7995d77c8d114120a9c7dcd3758c182f8382f8f0ab8cabd451f71c72daf985ea2f64d85b561dd294c2f96abd8f351f2821fa920ebc8fe576aa4a9253cc23ce45e3fb4695f181ddeaa2ad12e96fb0c658e12f12cbbb4c244efe0b40b09c0c8dffdaff6f47a8c1f4ddcdf4c5e62eb68bdf66a63eff871a31fb1fe3cc67db129dcc8daeed2ad3e80ef54e600bf7494752d890e7183fe7f22f9ddd790d25a46621820b79203d584aec35ad52dc7fad76a9a7c69b276b7fc66ac7b873db7beb6d1c2f6bc8ddf11b9cab1b8e8b321ecd33bc4fa548f99cf116379ad7a7b20672f2e7cb6432cc2d792221ddb59ef4f62bdace3bf3269888085f703cf0358235d22f3d2f5b19ebbb5692a39282aefae8015e39425678f982eb31755804d4f1e698491ff7cc94157055a2276f8a9576022cbfa45982214f356dc4b5eb3741e12c3f6361d9f8334f175503deb9c03eb40c6db999056538c750c99a2f55d39cfd104f5c9e77c462b127007e5e24775726a9f7c841838eede9f90f62e35a68dab88147448581bf09cdcf927afb10c054c56f4cebc4b18a4e01427e0427d1525a3857d969c5823920a1b56436e8bb484d4f0e96e17f71db9da6d1317dd6a6029c4b6ed21fbef7552581d56d786facdff8f5a225c7593cdc9bb42c722f47ecde0967dc0a8f1a5c99ce711f8399f7a45489a80e55b982caaac1e2728b84674eb27c76c2f0b67bfd4e1c88dbb26e090b9f3e19954d7b32cc33bd331996dfac4187d76b75ae71e359c93bc1a848943ee06c933f757afbc1d68d63c8e1ddaaf100069f6160ed97b3ab56a36985a45ae43ff8504e2720ea0d203766a63dde7d9fb45e7854657f7a30705bb09f9591aaa991ae8df24c31463c83dd00d02ce3493b92e3f4595bb0765fac637a5132f83e29d50aeb53b2ec911d0562c9ff4972342eed56e85f06e7ddabc08b4eff380f96b56cb09731ac82398e1df085deb8083b61bb52a8d473417c1d3ae2be90de8435a062783477302d2fa8ed939dbee525fb5804de60ad4abfdf4d02ad41453536cac2c9d5bdc3786628d3fe45d42fdea409443df330e5fd0f4858b6cda8c0a63d7b1217e5dc771bda256a823bb30720e3dcf2252959489a638089bb89aa24d688143a6b1a76172e7f0d5dbca3d033a369cc2af5f3ce0ac4ddf2255a80c23e2d467a96ad105de238cd3ae03ce1151aae6888f3dc54fe3dc07307a05ed4b0844363f0af2168f64d7feae7059ee1dcf5a10098f402f401cdad049fc4a81e1c9527c973bf32c8b7721d1b88f87297da77395debde40f1ae549eb56b2cf6ac15a7b2399ab5d96692a82239cd5a2d6d469a64b3a3154b2ae81e9a42189efb498ee86441dd039e38ac1204a286cd6d08a2218ea2e77e6379b40b81bdc19489a828905701b5e19d2ad82b7e885310007161a86a21e43fc70012b5f2c684a2cf546d9f623e593faab383cbf5879a871802ae4c9d4879bb28c5785b2d6cd3a83c8600befce72c187d48f5a879d9d9e57b3c55916b097f04ffca9aef8e3e4574bfc7db6a505021a800fd79a856550978a899dab650389f55c0654641890d0dea6c8ec177216cedbd29395a126a66c376d432d20d0bd00b1d7c1091f85af2dab7d4e60204beacc90a3d523b0be21fefa5f4e892130379c2f947889a28a2eb2dc8cc2b7d0090d41db53e9279b54e1243ce17089f946d112a5ffe1ce7dbcd4e849b6b7bce239b256005d46f7f1a2e2af1a048cf4218881e015b6cf4c7f6440f5fc61197f79749da80dc9ca03e2bb23afbe8e3656036cea31ff18ff07368a4df0b053c2d4bbb3b929bbf42cae74c88004b93493a42ae204b156fbf785eff086b5fad30570e88dcded140f016ce113f4c8907ccc0387f3eb4958953d8cacebf890666f3cb312a2e87555d93132fa88c1fb685c96b4a45ecbd3d274909ccb1f5bdd2d392a733de7cf1c87c3a8ea4ce905141116b2037c7f5adb387cf618deed6ad796711ceada04ff33d7930186582756d7b1c418ef02ae7399b431b38198c131b7a747407e2d4f08dc19f8a863e808ad6078caee2c8a1554d0f582eccf4ba0ae43afeb9cc62e2a5909ca81ba28ece723e141a7ae3317afacb3d0b61d9f199b05cfda42b750834c5f57098be4476fe2bb690481e7cf509e5e94d929b256c6df712a5125a12ddddb68e9b11dc0523cfefe2fc431185b96c5ddccd8ebef1361e2e01d812da62781e29c934eb89d59ec45adcd208ba6cc4735c59711452de1f1869861e7c10f626ba3b0872e7024b370eac3373223129dc44546ba9354d094bf745bb0e3ecea28a26cf1d3750f23276cd4954a08c05464eaed3e5610e5b4e4cb9380", - "tests": [ - { - "tcId": 72, - "comment": "private key with s2 vector out of range", - "msg": "48656c6c6f20776f726c64", - "sig": "e38e198c1f8a94a183a90afeb416b870426ba739bce98da1e72efd600f13d38e2c0a51c6560fe6c1ac2fe2de032390fb1eb990978269ed755018ec478bf862632bea446cc6226d0bd018488fa7f8531b4c72f94c90915deb640eecdf9ff8114c8e3710b08c41314b2f81ef952eed4a3a2c6cfe9f42169af472e93a8722273706a3ce8c620be45ad9398dba3d666c998d263e35c6aae43e00835630397597f3cd22bcc6bebb56033a267105443f4fa0faa82b5637cf19035e97731e0259a2812f7432da8ecb2a8b2872b0ad5705f5f663a47f5351fee175e42e3bdde05a8d778bac9d17e80c647f667df6486e42b3bd64acf37d6c0c071c3766fcb0859310bdde26ffe2900b5bae5cca83281feac3a754ea92d6de02159ccb6b809e3cb1a9cbfc63356ed339581484d8e42cb350e0d7b13cbf0e2830e6a9dd0f45285cdee709a5ba20903c5a1faa4b765e9bdad09a96867b909e6db4fccaf6437c0d70173e84a92b729c926790e2d8ae3316f4ab4b41e326188fbcd10cf60d7a5f59734eaccd3e831dec33edbf66a43975f94d03f67bb0a7503d9342b61c1b658a0bfe65526347a1565d69d7dce2e9b633f1216112599985e714e27e6003473ad6559c2338d60ec04ca22d748fbc07b4bcb880ebf488e6c0be5d21d0d83373772123ba8d73a6cf9533a80827789d3b83353e521ac1177d0d8417eba2b98136762655a8f5a2c9d4e0dd54befe06905b1ffbb1dc1f7bbb5056c388a2fc0cc0550ab5e772a4c99ccec57ba217a89b437741db46c5c08468639d8b9cec4f9a9c4e4ed109509d8e8ac45d27f3c2c2e7dd1640c7be4a431cd250ca2756b319341286699e4483c9860d88dffc38dc212928c9e73c4f0c682dd95e436cef28aa861e8f6179d92534d998fb17eb5664d02c66ad680a7c12ba3988cbe8cd601392e8c243192463c8ab93fa68e9f5872debb3c6dcb0cb91c4bb2fea01750b3e8b055761515aa74d3116115eea65748adfcb8f3ce66ca66ca81327954a95a04fc9416604b6c9a2f9ad794e0885f1d5424ca10b3d7d8b28c5211eec82bb5d4d3bd1bbb82555c7d0faec1f78c4ba885f0228542caa5e8f9d692839dcb96cc7a0608a38db772c4522966d028c55b06011a411f3cf1de98825eccae3019f66299961774fa65e54ec685d2347f698b99672870df8d15b1894c174da61c7b09ddd8ee971eeb21f7b685fbbad1d2dddcb553d8814abb34edd4e769a1185473b4d5aa425b212ea744c34c99e7f6a23875256a6a166d4a193acf20a303e76b555b4038f30724a427daf695198425ae541bc2cce403206a58a5b01286403d5534eba27c21961d92d169c1489285beed2b46fcc0ea8d96008ee5b4e31e4df2700ecde20a0fbd18c5866860b2a408028f1b0366899a863c797a19d630d3dc1aaedf4a72c6604fb1520e2c1f4bd990406a3cd66f6685e8a5d5514f02427c9f48be799eb6e60d88a5747baade73c6c29890ac1c2cce1c706b9446963b54e170e45d764d7c2079e5ec91dae31619fb9c7660c818c748e68cb77c96606830d941efbbfd3acf111517b0c4d4a9badf954c58c0669bdf8cbf4a7aebdd95eba7c56681e8111552e2e5622bbd3b4df3f0d79a9f23b92f96aef4926b3660e8407b14899468ecea5d7bacc410a1a04e9e4636bbbb2d1e4b5f4e690b12acc453f28418a4d76daa8eddaee29494b4d1fd80ca86575cdebb6c4817d16174cced964e6ed4c00d40cbdaa1ff86592eb870ee11339f691f01d7f5d0d2dec6eb064cd374d30a97a3f34fa4d9884c002c642791c27074c02cfb631eaf412c4a3401d5a4c011aec0f13ade4e42fb1c54ff0a453e2a3d912183f9bccec6a3a9d5b3ed150a5d4b1f864b685deffc941c1af2b252f27b01c831879dc660fed23365a8f538e8ea45342ba34831ac11156748706b1291481e796382ea02212b32b0db62b17674571f25db552f16f32d8a41ccd069ae067bb6380836258d8ca84725a874cb600920d76b75bcc462fb3dbcea102b5686ad7344da070967ba2251e7d3eb6f6fa1f0300d8f639484743d5c3bafe5a553978e183b89f6b7fd097eb53febcf2bc0281bd2c32e347adf2429372d5d7cec86d3f122a33655603cb8a50a93401ef9f3bba4ff6c809a93e2d49ac15de8a54d2fa7cf6659dc48f832769957c31716077a8b1605e644ab207479184719e0e46227a523fc1414e97a1b1c041be55bebbaf0b220426d36006939cfc33836f4d8e0532ff21ca001d5980798d2175b7fafd7f80395d525caf52fd90d908acf7dc45ba9855456627c860c579ea74c28d4e67d8d64b93fe4ffb1b8764808ea4bcac269efff956dec080668a4472cd4a524ccd4009912ce69d3b005495df3298c112d76acb9a2171b020f7c245cce59b5ad9bca40a90f3c417d6a7f47b5138896735e5866336d665f0322e2d5b6110a2c49b8457895751899f912a33eeb79b1f3359f0fa0c8e9f7bf7b08d870524b28099ddb60bac8ee821372f3799f2a7eafa964c3cac3e74ad7a3a46f6508321b5da2abfd791748a7a1c4ec3868cb1af91cec7c4858b532c7777b73a3a5711b2880e182079b487b1590e2f9119b2a19af7ab8560bc3f89418eb3eb2982dc2512106ea7ef78967675c1bfb937e019936c82603c2ba920b533a483f85a468f7c38e6b52654e0d10ec4750ad1d554e642ed53f530a1d6d89d984a5fb02a504a8ea5610582342595895fedb2514bab4b568da19c35c0bf422f0d40d59693ea245f7a05b282ab6636280f3001c5fb45ebb10f9e031b16113f6ac3f65c732c38d134693b2484a33480a7eb671dd6d7df47cd3739381c8349d3beafb551ad903ea22f0c0047d8356bced4e1dd8def0fd4c51da4e498f4efacdcbbe691ff1f68b3b0787284004641a643325c765a82c68c73c458d58c0cc23690e9aae2320b2b1d5045dc62b32ee1277cf27ba578109bdcfd8bef283eab6814c07414e118dc23ffb1164f8487ebe34fbd8fa27f9f6f7424797db403910631c12d18901c1ef32f3ae522682475c6e864713a4d3ecf7c492ea1abda9b138a994249a371ebcc48b5dfe9ceb2ec44d8472565f1f4a5474c869cf5ce5741d207473d56105b1e589c3cab583d89447a5c2465d6121f01818731793a876539e5fb8cd90ccccfb63d15eff0e214cd223ec54a6b9b28beedab721aee3f02ce64bb3ba4590290bc299b462d77e14683c611adbfbce2eb855c102c196481c73637df400731f765d525932b8f976c275a6a03fb4861d06540817fde3faca07909e038d2e45a76af526fa014a8764c702986c495d409e6f11842c0b7f22f3145cb5ba56e5bca6ed6cbfdd9d79a894606b982747159c7396794b111adc9f73c16a7b1287494d4756fc52d71e39d2dc87c9d698b0a262b69ee3d189125e664d303dc9280277c062eda6bd6b57841400e806e642ec7dfba6d9968f16dbe8cfa1af146e29aac96fe4bf1840f0dab6d371ae922d88a9b204b528f31e79f5d1e7ed67e36778ce5c2643129260b937a09ca245144fe10faf3392ec6835bce469afad03eb6804a95642d421a1963b34bbcb604cb494ca58c5b52c11e6c1a2930da061d779e10e80b88fa40f683a40d865725e4ae7ef4b3045fd3459e077e34cac939f345558d927ccd2338f8f037c6a5000dfddefefee24f3f0de6715c0d85385447a70d2aef6772f26e23f158f9af0131e6a2f967a5d0a54604b1769eee4390984a4ffac0172f592df4b04200535751135a732b7e6ff373057953014d35381e86e9678274630df9ed86e0b8ec93f1240305318fe889b35e0508214a6ba9e2e2f2c9b142932da60fb7929269bc3498c159e323638b9ec7fcf2ec09213535a1250fd49895f5a63c3d22b851239f5094aaadaf58e88ca8de975a1bae861439a6cb3dfe67e615fc1781a11327335fef08a79082794daf5cca4e9fca3bd60899800854b01c31de872f625bedc4f1b6d659584181b1da46b2fba689e622e255f05ca9a619a4fea28dbff3aa9a5dd84cbacf6ab630b855aea6ec6e9dbf95a4815ffba677af4ce6b418a4030b68607d5edb7e470faab648156cc2c152b21a381469473e3c0b174a7eefdd8eb4a47061b883123325dccdb54d8b50412a286e940224069810181be94b3b2ccbd40aabdef6aeee34bdf7c7009ca614cbce081a0810e42ac8082ea6f618fef92a302f5f54a93e261fdac80852add599c4b87aace0dbbac0585a04812f2dbf0185d9c06b24db40888ffc5ab02175debf3c4883fb8010de69a2424280fdf64008ab7639973933945a32dfe185823d78c4ebc78e12d2cf656fccb603825d81feb35e9246a5ed678fd2ce6dcc12c7f89a7004f32f4a3470e040bfda9f6498ce518f8901261521847b64e3350d0a5fdce53e38cf889f79322698c826b489c4836b383c5a06ebda047b57454b3c1fd446ee37d7ffc2be3b4b290210aecf24a3f15d7c94d29009d79b0a66bf620dfa6c84070ff04da280c244fec671c6af6b8dd969e772d056ab8e9496334baba49550a991613873f6e1bebb432ac0787c744634c1ee060121ccc8d35543b289298579c4f2a6239139f74e8349634f85a03068e4b01b6d8891bccce4f80c0d3c404547539bbabdc1f81b21242c4a5557bdc4092a0121304adeea0609141ada0000000000000000000000000008141d1f252a", - "result": "valid", - "flags": [ - "ValidSignature", - "InvalidPrivateKey" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "tests": [ - { - "tcId": 73, - "comment": "public key with t1 component set to zero", - "msg": "48656c6c6f20776f726c64", - "sig": "0a4133248382bb1fe24046be1eb9fade39090c9428222eeb9ac835c76ce6baa4c40121b2778514c711ac2981d174a16b000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "result": "valid", - "flags": [ - "ValidSignature", - "ZeroPublicKey" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "66239a16589a522a029a216a75a70a5b1c9c49b6432bff6e4be262d4d999c01da4eab195cc9eaee7ae840f2917dbcc0218e6439d2d4198bb0db2b0e73fb40bd1d9daf16a524c0311c9669874b0a175d8b10d5564f1af8007a1b852d1576231e77b19b7efa5cf2fc8d3869bba336b205d6a3ad7a65fba36962ef7ee3aa290efb35760bf9fbd58894c0b51bc447c503245cd5e62b0690eef1b17486080a2e5d7f354225abcd11d8e8165f7bdea98cdc9fd887193eee058913255982ab3a22ba1db732e0645bcd3588a8b3c18bd929771e5d9022c383caa1b998eeb5bc36c01936237d703e283caeed671c8151f6de810be4d22daa25a862ac16a622c4347ec92c03d6f12587cf5d660cecda689b0ee75f391aacc270946a36242837961723a99e279e12a04a331a0511b021be538dee6088288b69494292b7756bb8b50cd14fb583b64dc1b5ece98f6389ef07eea028bfe0250320c12a8e24a4afd83df9a178ad3176aeba108fb3b102313a03c9a75e1cf3f7ea6094c2fc7480415672d4c36826435ffb2332307847f1a408685decfa42ba62c9adbbc995aab75ef5a45adba5ea611783b7e9d70002fc1ab1882184fbea63d55ea407243a4db96d696ba1cc5c5699d87bb2e123f9505a030137329ecaa5ffc08f6c258fc6656f2b63dcf7282bcbba58fd11f3cab395c488a429a019c486242dadeefc6352df77aff70dbf02551945c3f93c76740e63f63aac39a26c55341d14e8dcf3c48be7f2abfc5a0fa7d15561b992794b9ed008962b1d9b163a04045c5f6d070194ebfcc770eece4705aff255cf58ccf8b648a56aebb125ae5c4eed5e3cf06604b1f66fa4fc758975ff7a731450ab17d3dee55986dd26448a6ac61374e6ce22d0f7c7e40c2d6b9bc67507b6bb673671d853fe22ab26f555cf3b27c255fe0796922751777764753576abd8f244711020b4a576b620ae433b79b87d9ee6616f91f2b4a88366c78e6ced025d2417db695e120d11baa8883eb3f8207a8d66b61fa34199cbed90dfc640241470deb788ab80b3e4a8383bb13ea34d7fbdd0ef516aa5f8426d20b166b1b05d56e2da1554bcc196225481bacada7564ff59f16291eb0810056e2bab1e544379c2ec7f7af958aa7b815ddd2d254a066b4e35bdd4bf5608f9d3eb54b1660156936248e71915879a3e3df88a373d43f7595ad166bf9e84b6a05531b70d891234154c7e3725ba363816532b270595df2463b1b2a67eb0f95c1f6a5434fd8595a3062b9ac92a6352780c7d078fb045831bd057dd49772e4b3db9806139be864f6bb8d189b2ca06255db60d8c07e424a740dd30ed77c177f526d82cfddafa05ee5cf9cbe3fb275589eff005b52005f63da6dd6b1d39335f202af6d058b5caebf29782a22549814c1921ec1ca21805faca60e434b0876754249caa34b21903f874df5e4548ad8d4bbb0bb2f05ef377b1c8b294af53c7bc696353a850ec5c33c9460872bfec382ac0392b9928bddeba48d24819a500a4750d49c8eeb9e546154b5b8262ea59f7cad16478243659b246740ae61c96e4c2e0213eabf5019040ee9369428f833fe4163d54ed3cbdc5fd32304c890c34dcff1d8c3b9b66c40a13a3c21ac0ca1e69b68361a0564743f9f32c252ca370e56860a154e4033e5fcf63a6cd1ca64deef46164286eb788f87d9ee59c6899ab7aca62e3698639464abbd9ada4023b87f45f1ee05ea2d5fb72713e9aaa91df5c483f54cd19eed9408b94c544af3f3758a6be0933ee3c24edc1427cdd15995cb32b8ec89e032ee949952e6ed7e941c9943e0dd486faf28414a0795eb502797d8a7cf6ca3f051eaaa5d7fb20e86a72bd44a97af6dcb41e37ce33813f0c8f17a6e4d2e2ea506811083ad9a93aac235d7fae01ecea29747bb94552ed1bd581e86cee23c4b7e60b59b09be4b3856116d7f5f605d648147371117e1baba9150baebd49c624afc9a64dab54fb0adcdf7d6d84e64b82942b114a78d824850d6b8719a4b90f41db28b51f351d7059549b0427c83e629ea838cc141f88cf041744749c41cea2bfab0b72b68c355bfad32bf426515b1f675f08b23f8dfe09f103272de8f00c16741163eaf1e0beaf3c3b02b3f729d4fb94aedfaff3c0cad893877cdd0480e61e390ac74fda52f2370ee95092cf24bf71ab46b7f5200b1708e5119779f3aa68ac163ef7999d9a33bf627d15f5fe18166551ea2a5aaca0655869f02ca1cbfeab17e3a2c0b34abe0092f154975fe890418ac191ee6dcbf72e489ab861393220a528b77cbd0de2599efb5b622475142d223fe4a3c5ca68b003766f84b8a3cfcdad05802d287ac4b4d4274c2aef41eb38bbd2f2e5ae9a65d138da3ae32b2dfb33f836b9220db288902dacdc1af9f65f85d9f6a8836132c258475f2511b19a299094f03b5abf4fc02b489efbd4877298d521be2dcea7141f291647ed63f0927710ab816d60b8d72002e95b5d77c0a5c10c346962d06396cc521ada3b3550bc3b3d4cad602da0ad801246d91d33237283d3e50f0d52912b99d9de026be4e84bff5560b9bbe615ae567a378e34c922c12f38d8fbd335ef64944597e591cc3b95b7dbf106646d45926dddf46026d3b4de890f093f03abc77a0ce697cb64562a676d93710d144dee2aa22ee7f6c7cea94b78e61f2c228644d9af00200afecca9ff44c4cccc5dd6f90445deed048edacc3565bda5f3aa1177189f83bc9fcb8346a20d39a90def25525e1468b25a59161108108220a2f6e25", - "tests": [ - { - "tcId": 74, - "comment": "rej_ntt_poly (sample_uniform) requires 5 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "af2040f9d90996985b6efd6a6ef90c465369a9ab95efb537c85f137d528d26ab7a4d5035efe5f734341775263e3b117d2f2c5544b0ffffe4f548c87846deb2d34af083bbb07e3c358fc78bfac471259d87043094833956eb4d9b23d1acbc7efdde13ebc883290783e33d743bb10a13bc8eb2a2e6ed552d8a1780055b36fcf0987b032487ea60b8f51158016982cc2aa49318284d5e600eb36c405d62ac7d6c32f88b1f5d41f5f8d5bbe3393033c51a95876c0f9c2124d6d87b98634a29269be830da07725cc8621b64480492af23c67aad018e44c2b957930e36171d1ef3cd6311cca9ad14e1c58a7d6ac6d2cee66319faab0b0c92533a1bb98eb909f5feae67c16e4e29da9be03daf0092cb2ace5a4316f2a6781109c19c19e2d38631e0aaf91aa27c8b82c8def955152bcfb7b2df0b2ff0b04105dfa209b3d9019444685054d439ae117c6f50faceefa46dfca10bda1213237f898143d42c9f83bcc9672797d4a03094431567983c1d8e816011bc4e7190e3f6555fe9bf77ad61b8415b52d2a36c62e5f9368b6fc0e7dc5d82c682d46cd189abe12d933a783fe9f4b46f87b705d0c90386efd551829fa995942af1bdbec31cbcef50fbdbb7e76615dbbfa9ad581b59aef0c922a69de190c16e5c4b0a3d6f0141f58aca58965e100b50163beb67f9c57ae8e79ac5aabb24bcd3600015cc65cec80784c9d05874610350cd01ac43976276f0ca6163d99d495f034cbdb9e39d24efc1ac9013dcf380ba1cb676a6af8282473868e61ff4f0b13aa2325aca910dcd767030b2cc5e44fa7e17c32786ce7edc9a432db81d6654830a16b3b4e37c12617898d5d2b634fcf250ffe545f4da5a289d470dd4ebac4362ec08ef04a31e8021a8c760fbff797773058ed11d71511b5d95f0019240743ab44527db4d613c2759357c291e7679d06c930ee435ae77f4f2d13c4e767b7adcc32e373efdea94fb70d6aaf96e64b28ed4fbca86ff1bd2656e392c8c4707e3ac6ad8b0c85c2ed19328b942f3af5eea89a7493ee8cfdf86fad43084ba7582fec07c1bb5649d5177a312d1b70f7930dc1ddad11396e5e315ac7f1d3047887a3a40a85d809f72b2661786e311928a6e61ce7854ff854daa170b9c406feebf3dc33656c9153b9f5e44aacc084bbec9c06e79a103f2544d6f5ef06e0f525687a10f48f9f08dff7d6f5b467c287fbe15b33341e3e44f8b27a87342f40dfbd20ebc214eee221115abe3f8620eaa424a59c7fa038d8969a5a95a6476e65820afcee40062e14d498544a3ff95e308afc39d241e1d8e403fb0570e2f6242771f20de2c792b6bd2996e1214297b1fa72c6843cb4f7d0196f9a40716385a3a5344f046e33e2fb089ea1f08340ccb563373795aa3e2fef7a8509d7ca174a5b6cbba90a56d743078bf9dc37fb7887187d6b201c5b6cf0638fc3e36d1db8611c468c04447a4b670a5cb55d9178a3ad2cd7817fc01dc8063161a1f9d460c831208691f30aaa4b365f074c601c6ac29056b7dc2279ae6e6467a7c2476f3fc041dab076fcfd5a9681511283cc1dc59ecd5472c99d8b8e87e5392eab30d25eeb40cfe4b7e3158d307b690706c59eaeeba9bcc6cf3e7081847789cdb83c55a3fd77ad8952566cbe6afee69a11774f10d9272ac6351b2c086a7fba26bd36ed0ba252d7b42943185235180beafb9154c93b5f87fb7561b3cb0aa3964a5d0aa4925ed09c90c0c18798091ba0aec63e3f48bca675978050f201aabfb34cc6f0497b773c2daed9178bdec949f61fa267a83dc796af329bc15d38994135fa2c97d0f805807105123a76b86cf9c82b8879450e942574a5fe2868e7131fb66be7221b4fbd25e6e19004533b6a3d12e91b058eae18318d0a5f324b0f9528a3459737af6e25e8d2179856ef0bd9f9de025e6afaee1ec49e8c98f9b96981af3cb1ca1b1740fb6dd86d48f7c6ae9e8541dccddb505a4765dc5cfc2e3caef4381a237ca2167f263f3c5f2db11eafc52b21a98d9c54619ee5c24cde5dfc8cecbe5bd086ea2a5d6616ccb47c0451b24019373edbca55bf23d1c365ad361a21a1928d72b4c8061d5cf88a956eeea3fcbc80609ca751b5a9004d887102e93867c4ad70f09105a666c3b9a575af0eef9799df422896ef11ad1281ec0032877520162bd52d59351e70fca453e4f2c85b23fc154c2a294b1d5ec0019c7754215efbabcf82c1e7f94d5873c0a4e3ff121e64c85b83bbe94bef011d9a9c8ce9ca692f177f7d0e3f499d684924dca2a653b90b9ffd485bbe88ed87237abc4ca6b55c3b71850a34dcfeb1d3efec5c83074bfd9630c308b8d94ddcf79fc813380ea7426fb10b2b461281bc38549a38f280bb2a3032c67fcce24fddacd8683a1798bc6cfd6add30c7b2dc9e04720f5149e1b1a6a39b4ec08a0c093a67987b7dc320bbe43f05cdafc74759b87cff4731af336445993f685ef5dfa3db636b830ee33bb45c5f51bea8ee5cb9ed28a4176140eafa2c0ef593b40738b9857f8ebfef3d2930387a11dd5daa630b8fb5744fcac692891e8171f3ff0a08ba5ac81cae0cd62a364f1b51caa4aab3085acb56a47cd75eafe860e92a6938a9205418e39bbaed6cd6fa9576906e17c57682b755314f437dfe1efd5c56f6782f2a8fcd489f4fdba794b452c7ffb45b9325beb72af3e2e77f1a3a816b1e5fd25d5e3864d90197dedda58375ec4d78c7302e787902dcbeb173f43da248ceaa8dffd1ffdd23324c4dcb1346332a70dcd08090954afdbd27cd3932e9acc2e9c889c02826bef84d077ff066ea06261601a9a06e5f3e8b9732821b56dbb2b0fe476ebcedc4142b9c8255c2fdfba17fa5c7e0ddd976dd0c9e5b1420aacbe03e34d8846e8bf17f79cb82038187db482957e6c054d33ef5b63937b7f64506dc384a99e47ed4eca348fb5b62a3639b84897f17b782b02131688a75435caecbcf7cc0bf0a88615ecd2ab7af31a0cb5ac6c3c5e3c4696e4b10b9c9f4e3323cb1817b2e175dff035fa36714cf95f8e151fe712bc38939bcd47b50fb202093d297081579637fa97dc8a0690efa7c2ea071ba4d4e1896387115001276d3cd28fb6217bf2ade25f2a3eabb81d08a68bce79a58ba971dc1feeaf248d47bb20dc93a68e3f32d19658cd3f1b7bb2c5d798d73025174ae8caa6d8a25f1e0e3bcdbd90a2794ef9ae032005b6b95b701c6122693a12ef18dce8609f3a48c32cf79a0d04f94bb4a6b74454e09c0f253539b185a7d5793e05cbad6a7ddd79d80d4e48934bc2e610f7fa49640d2536a0409aee11bc62b2f4e8070ccc59038dbfb7aa2b17acfa7c841b7d943c82d6efef90dc9349a3bcccb905dad4a3beee4e867581cfe8c31bb2c2f3f187a408d16de3737865954369b41c9459fd7cb3b7ef86d3cf5cb1c3ac9b90ba78049ed35470997f15dfb8c2e02033c21b8f5bad83b842004b43de82ff88df93f2687e67467990b61511af8119c0ceb6ba255a22c7479dc06036797a27067790e3836c481cf904f9f6b484f67561aa3ce9661f95d8f67a5028b527d7d530aa1b92c6a6f344b9de8286bdc755d1e973884e402cf37a3294a873a93229689f9c5018aa151d53e4fa78aede7ebf374259ab131d9695c69232bd2c14aeeea9c1b53635b733965f391d1b1d313d0e2ff7628398011fc95d52b07cb25f8404b6fbca17362422235e119c03a1db85a6d27657822b17adf9d591dea9848e748b6ce07a28d830059700d64d47490bac5a94010618ca03c1654e81a01c4a6d93d86115f16d620fa63da2a7605ce50f97e56a020bcf22e716cbd76354e9896a264cadff5d367de89d8bb48999d6164bd8f7648e4ac0bb5f2652336e72b445f6f0232920d7a00eaa25dd6a0d46d8883f48d2b2c10b72036c6904d4d5d093f913ce625922a146f4e7c908b21a8b8939dfdcb275b5fe5b52ab1f446a4fd2a4fcf5a4bb1d0c9c3c550e6f5b0aadc4d411e87eacd585ebb8c4637f9c185cdf7b282c387ad49f8bf0b3f8c2fd63f9336c0c8c4c708b9d3fff0598cf134a9d205914cdbb3802f0eb5fbbbbde18e0fa2ab4bd3ff2005f04dbdf80ca25e08e408055ec2abd1a345845311dd8dc10c3ab128c7389bf2a9f06184651fe332201020f711bfbad269ba8c9dd749ba727169c6662e319ef0013c97c9980e1e0cd275e6bc51316f0f83a57d784c639734ede4fec26e670976415b7dce3eb197540088817bebe81f361dc992d16151b8a38b88ae3fe0fbd080a1264a4a73526b01e34495e411aacdf4ac1c893f668bd095ff65643d42783a758f8f712b906f20f284d89f6efa1453ae06dd0357297214b9ce7944af4f40e3ab8817b56f1bd3fcadb9d9f366d34271fc3045f05ed2eab57aed068ad6110050e64adfa066923baa566d9c2898b2c53bf378aafd2b21feb94873fa2e65496f69f6f94321590b43f409947e996697bd93f03e3337286110a262310e0072bf62355b84099106885a05cc1bf929a42125b337a7ced1ee2ce0f7be5a68f82021027761c3bcfe134e5b554d7f08a709a180d779152f7c85eee0af248d43631edbb845a1b4a27b09cf8c69fb1694ac69060562114daccc9ce702f6eee20398c04434471777b9fee2067a5aab0c160c3cf3d5a71797eb3de000712161a3150708eb7c7d0e8101f343999bcc8d8ec000000000000000000080e1118252e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 75, - "comment": "expand_a requires 150 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "af2040f9d90996985b6efd6a6ef90c465369a9ab95efb537c85f137d528d26ab7a4d5035efe5f734341775263e3b117d2f2c5544b0ffffe4f548c87846deb2d34af083bbb07e3c358fc78bfac471259d87043094833956eb4d9b23d1acbc7efdde13ebc883290783e33d743bb10a13bc8eb2a2e6ed552d8a1780055b36fcf0987b032487ea60b8f51158016982cc2aa49318284d5e600eb36c405d62ac7d6c32f88b1f5d41f5f8d5bbe3393033c51a95876c0f9c2124d6d87b98634a29269be830da07725cc8621b64480492af23c67aad018e44c2b957930e36171d1ef3cd6311cca9ad14e1c58a7d6ac6d2cee66319faab0b0c92533a1bb98eb909f5feae67c16e4e29da9be03daf0092cb2ace5a4316f2a6781109c19c19e2d38631e0aaf91aa27c8b82c8def955152bcfb7b2df0b2ff0b04105dfa209b3d9019444685054d439ae117c6f50faceefa46dfca10bda1213237f898143d42c9f83bcc9672797d4a03094431567983c1d8e816011bc4e7190e3f6555fe9bf77ad61b8415b52d2a36c62e5f9368b6fc0e7dc5d82c682d46cd189abe12d933a783fe9f4b46f87b705d0c90386efd551829fa995942af1bdbec31cbcef50fbdbb7e76615dbbfa9ad581b59aef0c922a69de190c16e5c4b0a3d6f0141f58aca58965e100b50163beb67f9c57ae8e79ac5aabb24bcd3600015cc65cec80784c9d05874610350cd01ac43976276f0ca6163d99d495f034cbdb9e39d24efc1ac9013dcf380ba1cb676a6af8282473868e61ff4f0b13aa2325aca910dcd767030b2cc5e44fa7e17c32786ce7edc9a432db81d6654830a16b3b4e37c12617898d5d2b634fcf250ffe545f4da5a289d470dd4ebac4362ec08ef04a31e8021a8c760fbff797773058ed11d71511b5d95f0019240743ab44527db4d613c2759357c291e7679d06c930ee435ae77f4f2d13c4e767b7adcc32e373efdea94fb70d6aaf96e64b28ed4fbca86ff1bd2656e392c8c4707e3ac6ad8b0c85c2ed19328b942f3af5eea89a7493ee8cfdf86fad43084ba7582fec07c1bb5649d5177a312d1b70f7930dc1ddad11396e5e315ac7f1d3047887a3a40a85d809f72b2661786e311928a6e61ce7854ff854daa170b9c406feebf3dc33656c9153b9f5e44aacc084bbec9c06e79a103f2544d6f5ef06e0f525687a10f48f9f08dff7d6f5b467c287fbe15b33341e3e44f8b27a87342f40dfbd20ebc214eee221115abe3f8620eaa424a59c7fa038d8969a5a95a6476e65820afcee40062e14d498544a3ff95e308afc39d241e1d8e403fb0570e2f6242771f20de2c792b6bd2996e1214297b1fa72c6843cb4f7d0196f9a40716385a3a5344f046e33e2fb089ea1f08340ccb563373795aa3e2fef7a8509d7ca174a5b6cbba90a56d743078bf9dc37fb7887187d6b201c5b6cf0638fc3e36d1db8611c468c04447a4b670a5cb55d9178a3ad2cd7817fc01dc8063161a1f9d460c831208691f30aaa4b365f074c601c6ac29056b7dc2279ae6e6467a7c2476f3fc041dab076fcfd5a9681511283cc1dc59ecd5472c99d8b8e87e5392eab30d25eeb40cfe4b7e3158d307b690706c59eaeeba9bcc6cf3e7081847789cdb83c55a3fd77ad8952566cbe6afee69a11774f10d9272ac6351b2c086a7fba26bd36ed0ba252d7b42943185235180beafb9154c93b5f87fb7561b3cb0aa3964a5d0aa4925ed09c90c0c18798091ba0aec63e3f48bca675978050f201aabfb34cc6f0497b773c2daed9178bdec949f61fa267a83dc796af329bc15d38994135fa2c97d0f805807105123a76b86cf9c82b8879450e942574a5fe2868e7131fb66be7221b4fbd25e6e19004533b6a3d12e91b058eae18318d0a5f324b0f9528a3459737af6e25e8d2179856ef0bd9f9de025e6afaee1ec49e8c98f9b96981af3cb1ca1b1740fb6dd86d48f7c6ae9e8541dccddb505a4765dc5cfc2e3caef4381a237ca2167f263f3c5f2db11eafc52b21a98d9c54619ee5c24cde5dfc8cecbe5bd086ea2a5d6616ccb47c0451b24019373edbca55bf23d1c365ad361a21a1928d72b4c8061d5cf88a956eeea3fcbc80609ca751b5a9004d887102e93867c4ad70f09105a666c3b9a575af0eef9799df422896ef11ad1281ec0032877520162bd52d59351e70fca453e4f2c85b23fc154c2a294b1d5ec0019c7754215efbabcf82c1e7f94d5873c0a4e3ff121e64c85b83bbe94bef011d9a9c8ce9ca692f177f7d0e3f499d684924dca2a653b90b9ffd485bbe88ed87237abc4ca6b55c3b71850a34dcfeb1d3efec5c83074bfd9630c308b8d94ddcf79fc813380ea7426fb10b2b461281bc38549a38f280bb2a3032c67fcce24fddacd8683a1798bc6cfd6add30c7b2dc9e04720f5149e1b1a6a39b4ec08a0c093a67987b7dc320bbe43f05cdafc74759b87cff4731af336445993f685ef5dfa3db636b830ee33bb45c5f51bea8ee5cb9ed28a4176140eafa2c0ef593b40738b9857f8ebfef3d2930387a11dd5daa630b8fb5744fcac692891e8171f3ff0a08ba5ac81cae0cd62a364f1b51caa4aab3085acb56a47cd75eafe860e92a6938a9205418e39bbaed6cd6fa9576906e17c57682b755314f437dfe1efd5c56f6782f2a8fcd489f4fdba794b452c7ffb45b9325beb72af3e2e77f1a3a816b1e5fd25d5e3864d90197dedda58375ec4d78c7302e787902dcbeb173f43da248ceaa8dffd1ffdd23324c4dcb1346332a70dcd08090954afdbd27cd3932e9acc2e9c889c02826bef84d077ff066ea06261601a9a06e5f3e8b9732821b56dbb2b0fe476ebcedc4142b9c8255c2fdfba17fa5c7e0ddd976dd0c9e5b1420aacbe03e34d8846e8bf17f79cb82038187db482957e6c054d33ef5b63937b7f64506dc384a99e47ed4eca348fb5b62a3639b84897f17b782b02131688a75435caecbcf7cc0bf0a88615ecd2ab7af31a0cb5ac6c3c5e3c4696e4b10b9c9f4e3323cb1817b2e175dff035fa36714cf95f8e151fe712bc38939bcd47b50fb202093d297081579637fa97dc8a0690efa7c2ea071ba4d4e1896387115001276d3cd28fb6217bf2ade25f2a3eabb81d08a68bce79a58ba971dc1feeaf248d47bb20dc93a68e3f32d19658cd3f1b7bb2c5d798d73025174ae8caa6d8a25f1e0e3bcdbd90a2794ef9ae032005b6b95b701c6122693a12ef18dce8609f3a48c32cf79a0d04f94bb4a6b74454e09c0f253539b185a7d5793e05cbad6a7ddd79d80d4e48934bc2e610f7fa49640d2536a0409aee11bc62b2f4e8070ccc59038dbfb7aa2b17acfa7c841b7d943c82d6efef90dc9349a3bcccb905dad4a3beee4e867581cfe8c31bb2c2f3f187a408d16de3737865954369b41c9459fd7cb3b7ef86d3cf5cb1c3ac9b90ba78049ed35470997f15dfb8c2e02033c21b8f5bad83b842004b43de82ff88df93f2687e67467990b61511af8119c0ceb6ba255a22c7479dc06036797a27067790e3836c481cf904f9f6b484f67561aa3ce9661f95d8f67a5028b527d7d530aa1b92c6a6f344b9de8286bdc755d1e973884e402cf37a3294a873a93229689f9c5018aa151d53e4fa78aede7ebf374259ab131d9695c69232bd2c14aeeea9c1b53635b733965f391d1b1d313d0e2ff7628398011fc95d52b07cb25f8404b6fbca17362422235e119c03a1db85a6d27657822b17adf9d591dea9848e748b6ce07a28d830059700d64d47490bac5a94010618ca03c1654e81a01c4a6d93d86115f16d620fa63da2a7605ce50f97e56a020bcf22e716cbd76354e9896a264cadff5d367de89d8bb48999d6164bd8f7648e4ac0bb5f2652336e72b445f6f0232920d7a00eaa25dd6a0d46d8883f48d2b2c10b72036c6904d4d5d093f913ce625922a146f4e7c908b21a8b8939dfdcb275b5fe5b52ab1f446a4fd2a4fcf5a4bb1d0c9c3c550e6f5b0aadc4d411e87eacd585ebb8c4637f9c185cdf7b282c387ad49f8bf0b3f8c2fd63f9336c0c8c4c708b9d3fff0598cf134a9d205914cdbb3802f0eb5fbbbbde18e0fa2ab4bd3ff2005f04dbdf80ca25e08e408055ec2abd1a345845311dd8dc10c3ab128c7389bf2a9f06184651fe332201020f711bfbad269ba8c9dd749ba727169c6662e319ef0013c97c9980e1e0cd275e6bc51316f0f83a57d784c639734ede4fec26e670976415b7dce3eb197540088817bebe81f361dc992d16151b8a38b88ae3fe0fbd080a1264a4a73526b01e34495e411aacdf4ac1c893f668bd095ff65643d42783a758f8f712b906f20f284d89f6efa1453ae06dd0357297214b9ce7944af4f40e3ab8817b56f1bd3fcadb9d9f366d34271fc3045f05ed2eab57aed068ad6110050e64adfa066923baa566d9c2898b2c53bf378aafd2b21feb94873fa2e65496f69f6f94321590b43f409947e996697bd93f03e3337286110a262310e0072bf62355b84099106885a05cc1bf929a42125b337a7ced1ee2ce0f7be5a68f82021027761c3bcfe134e5b554d7f08a709a180d779152f7c85eee0af248d43631edbb845a1b4a27b09cf8c69fb1694ac69060562114daccc9ce702f6eee20398c04434471777b9fee2067a5aab0c160c3cf3d5a71797eb3de000712161a3150708eb7c7d0e8101f343999bcc8d8ec000000000000000000080e1118252e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "e5824f0943ad27a943fe7b1d52b8a42f689fedd9c6b8df15a4d9a6484b06c9cc61aca2fcdb02f00a5700846190e54a4b2fdf5226bc6a14fcefcea7345f2d8b797802fd6fb47c7e77f8207ae53bbb21c7523e9f0e445219047cd2bc563a69e20ea9d8be7a1c3a410efd030c3949e91f186b6e1ee9f42030eccfb492a75369ba21355c4daaedfd6b8d0ea6d515801dac1ce8dc51db63f51981944b886ce97c65b8e8bf351051ada80894dd1ce6a7c2254aacf85f6bfedb89c9f2f455a844635dbcd02b95c7d1e461cad965262649e9fd6cc45c78b4709fc8099db6d77dc42077ce56a0a1f95edb138000078c5b9b61b99a946f043b69f55d4690f5c296d9e38d861b0c21af896ddca3ac874251583d8510448f070ec9df88ac62ccd0885e7a84b421353e46368b4c80ef97f498bbe1ab0ca9c1569b7864640076911fc43c3c9ba8032f3bb167e4a14ef1ca3c56d1fcb4fac92766d428cfa34f4508cac2a1a9e54e478eed6524fb13da3f4a46ed7da67e1264b6b496cd0a6954229e948b8254af6651d6ccdde15c7116f23e67082395f434a9bbc194823063f0dd36a557e1e7618027abba2058a7bcd026d172d80906a733711403af0d849f7331b35cb412559e3ab63fdf5e0e38f40d2548783db596d2d6898f1d70957ed079bfa03511537059eb70d75ff181c5de64dbc9acd3ba1e952f32e78404bfdc3ab3e7be1bf1ec1806be8e18529962dcf0935bc2a31627c0447b890eb38ac39743f276ebd972e091a0c288eb2c60db2ada783a461013170583d79580c3ce852f22e61be682a3fa8fd44c7907754a9c5c1e76d89e9c56517506689e4bed3dd1b8e8b67f4d7aec8eab7a6a1b9a7c88ef7a7e7b0e9b6b7cb6d2d9ab204493decf4a286f33414008e0b1b3d5d94ff4f2974e20dc06e6dff7994161df5f1de03fec7cd5659a8493db03ecb8eaff067a41179f85486ebfcaac722de4f970e6d755fb7e58a999bee25c6e5219390ae1d8e4eaa5330be6a896c6f7c1354c27f35ab93f0de784075637d0ab3f1fdcdf6777a54784eaf3b2e59588a854a3702cdb6d38200ee3fd4792d406051c977ea8f6e9f13bf6d3fac051b0f609f6626bb47e3d4d0ba2b21448488a0acba0ea2a7c5d46071b69b1090090e58c26754eecdfc6402acd5cdc07c455caa08a3ee3ba7415d40ae5224f95758d46b8d8c250c998bb0688cd00ff96fb93ffb49d4416213a160fa5a302e02f13e55eb2b26d2825977a21b5ec9a845598c1f8810a0f3f4692e00df09f2784c82f336c441672f38652b83ab18d5910e6939b972b21c091ac09d188218705813cd3c974035fe6b2802c9fda09e5f538ededc53d718d64ed43f9a07801052750a10b1c6125d0453ba7a4c02bea74a7d72c29acb1b84058678035c086691b4785b7230154c29590faac95aca0da04e5a7e6bd065aa650d463191a84ed6ad33076e09d2856c0e6dd82e0e5a162a415e154ad94b482c5da2ec88a2496f6be342f4420e33e05d8fd2d550db9b7a4c10c49d955c6425212f1942cb860f20f70f96c44c8c446fd15d670502d819005a5e8abc71583669efc8e3e60f3f9170d6ebde92042462148f400edbeaa447826c9930867eccae05f0d9e713eeadcaa287e1ad04502f8058178c94864899586c56ca12f49d5d880b3d6326b7bc9da30384fe38c43ab4a270eeb0a8824ec9541e5eb27243b747e08473ff5aa46beb4faa55bc5276ae49cd287d082dfc7cf991e5d66f4eb2c0942072930e2f0be76ccc6a149ce4edb0749b74e8e3f95c2dccacce6fda670ef9a0e98ce0e0b7f34039b74c28d435a0596858585200739dcf004fe4821e18ae722a057ac7c6362dbed968da53ac645d971dc37ee23639ffc302ef99ceb1cf12561626aa52168499e68928c569572af18b3f436ebbf60cc2c889d24569de91f1ed268b96fd19a07ed179183bc7d96fe8ef2bd04f2e4b81cc47d9404770830cc68bfbd98d9ca3e4f57caf256331cb188f0497c8ad1bc4420d1934dd923f5837555a6e1b41a8603a4f353f5fe149a3c0fab6c9a3a895cd489234f7ca9fa44567998d9ef63c206f3398badc47c9d9773e96bf59f976b32e0d46c12bb70abecfb67b30e714fe043dad6b5d52bbfe1b48c16325a808f8978ffce281d777885f31f45a9283bfdf1d467a1144c453a29eeb404ad4d5692eb9303de5cb3fca5d7bfc2342aba01d5f37b0c8782c5f01ec88d6f8d2d30850229d6c777adfac00972cfe32b55bc5fac95494e6549f59bc94c61456cb8501f391fcbe8308cb8a0874cfdfe645effcde0dbfd34f0f05f4dcb81c4216b5995d4164ebf7f8d071dd997d4bdc333c0c5889b82df1ed89e0951ebdd60eb3d17cc27895bf8c4e166a77501c85cddcc764c43dedd423aeff2b5dc848ef14636d99280dae32bb9fd1df67802ad55c9af75200c92d35418a925359e20624e8e0f1e93d6d239977248bd2f4a2f11d677d69f318f6b2e8da397b49ffc4501a10cfc841b6366377ad4fa7d084a039518d5ca598c892c98d6e58446770df0eb2ac7834d4b113a74f7271db891d08e38633209b4671c620bdc4ec0e37aa521cc16b3b230ea6310e5765ae46aace07ecd31ae99892e2d1047c30643f608371b08634241d6ef7f7c6b0783c898d3764634944b0d8ad448ad0b1e407ceda319bc364a811691129d3e893106cc570cd64e17c861181a70fdec15ff038079f3825b8a5e919761e42c02c2f5ccbe6bbccb981aa5ab1e2a2124ad36cc8370416b", - "tests": [ - { - "tcId": 76, - "comment": "rej_ntt_poly (sample_uniform) requires 783 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "ade7527bcb0a6ffe2a2cf114e9d49d1907ef13a2eb3973f643043ac1dc03f88dceeb4217afee1203f3fdac54a13b6c44516c812e4818750e40612256faa649cca43f8a9aa4995b79af4ffa93c4478a0fb4b112deec6a100baa0c6270a00922c6fb38102ecc10df9ba0ab82c2aec27d546d8743d40ce9593e1c067c863b4732eb256be88f9329a2a105d7f4f9f8980a7bbc1fd2b8aa50c3cb8b15bd4d58ad2cd9182f6550d786d600da563537ba5afc711077afcf5f2ad27bcc885548def9c1865175aaf059dce6d3a623e3d40b1ce011e5440679a7567d0ebadb76b28fd9976f8245d2cc6b5b11789a5fd234136d8898f38fa54ab8587561c469c0cc60b03ddef90725bec23e7478942df433c1faeddbed06794d8e7e983a622b8602d245c7245e9b380301321488f904a99ee31dfa6c0c2418282954a2a8dd115d599f7d52a6a04d4f91b79d4aee5c9af7387faa55a37610355fbcc266050ea6912b81776746ec3c531c36bfe326d1976047ee7ace40e88e660bd25c69892cbc26da809cbd0b806808e19931e1d50a448f1f62b08269ce7d6ff3274cb88f6ed76dfe397307211924a23cc655474b174e8112be1b5ddd7f9639f4d22dbdf6ea48ac79767e605a733c2b4cffe2fd776fc7e16df770f6d69b527799f0e484862e298b8b82b3a811d5fa347bc9def3909ffb0cbede310f0ebfe1f89c1aa09301cfbfd3ecdea8e015df52bada77ae6eb3e4f1ef4b0b7197ac7b3348cdc6f27f95f6aee2827d954127c181945ebe05e564147a71a9abdebbffba31ac4db2d8dc7b630f48c3e2b2ee984f3518381b4db2129ecd17df588e27f5a4436b1314d4e9f3c50a10849db95e899a76bc9af091a61b1d0dd35ad75f33d33eaa1bcc1f3144320a7525cff7d4ecb2fafc8d4f6fa59ec642b847281e6e44ec3adcc67e4b10d01bec2d20fadd2d446aa9621937d51fd0cbd3e56a71eab9ab742f5db52510b0816916aa1efe1f16e97052abc39ec48e3ad2f0876eb9492f9249b20143cc62285488ed5d966292141157195c8a9d7b8082809aa0efa78279824f64c6221534fe517d18ccfd2a85482e716a043e582e8e95f03536026e98b49d6db3f78576b8f91a5107ef4f4a788a9b36d97e4baab8f9a32292a74099af38d79f45383664a41c0894044fcdbfff9677bfca7fb2b405d492a8534540e5310367a5192dd482359777e1419fb29a5ceb06d0ecee0723ea2f54dc9969e343876beb41ff8cb40a40664112852bb95c5a40c96afa5751a77a958c461a6d0e9a645f6577d624fc74f31a312ff6d2c8e3f5c7bcefd0d71e2950bdd5da7a5bc7ddae856f9d30ea9784d68293911421433f3fe963f70883ad6fa692b1aa6f01060340fadc0980c07111b0c829bf7d551d8557b7e211ac05c9657d1903078cb59f22be709db3fd9ac7bd37ece1e88f6cfd7b56af127e9e2ff57c46b9e27d2dae1a484845d873c8467be6c0c7bd1ac5bf860f2771fc2767b53d0132aa6c70990813238ecc663e4eaed069554fc35d91b8e826a239f87638e13a3ce82ee87f1283c2f64ee7d715fbaf03481df6754750212f941d159553296a11c3e5e99b23442a6052a1d13b433f74b04aa18cf5100fd2ffbd66088ec58c1d5799427d6787f7fa732d665de840bfceba5b78b6ceb6a42b5916cf8be83eaf5fbda9a4c92d3b3bde73321c1ebe7783a2f8c043647a8f59a2079f9e99466eb426dd9110c0ec36081019aba4d2421ba45d1f83ca4bd7c44b319557134ac8b973949e1b399b89f722d7e189deee7e3a738e760b1c097a7768af06d0f22de67bda64ad171dd8743cf72006d5fcc4f0862f4f5d8929bfe80ac40b0d82aecde6547ccc37f7c0427262acb1dc7af40147336af8b075df1cced5b01fc423906fe0416b89c07ffe69e9cec79a3221cd60726fe3e7a921779ed24453bbc286280ef05fe39557b1b529ee10ca0a3e54c7f03abacf589541eb02fb1d4e83db8da5fece911f19f1b8644fdc470c4d7995aa4858e462b288d61ae8f81b9cd39257e593467252cc77d77718eb705d332fd6e4d61c761da7aee85667f39e601f7b14dd7fcdc4a70e6aab78c7e429b9ad43fe959221eeb53a220899e3f632cc50db8632be08385bb79466e63ce406826ed24d5daa9dfd91ef0650086e8f67ec03e11e57ce0df35a87e36363731d5e6a129c974574c28c032492fc2fe450ff6df857aa2d34f88d740026c5dc69866e1818c6ffeca589da202db3243652d092f670b173b66e845ff249e0b69237cf6d73a8d7b6e3cb3c604dc9c1f08c543a3d532373c482a08b957fd77b78779742f7f180bdc41510a5c469afba4d656ef633540c4d55f3a08de2bb3aa13dbf72454bfa02cc15f900c9909983bcb89f465bc7eb9a9aba456c588cf0ac9689a313ca4891de90921eaec7a6ed5ac7271434772234d889382b32c6cfdfcb2aa6c4d76104ecfc3bb71945f54a707cd4851c7f502680c9f74a2ff6475c10728e843e6668f95f7f25b3b63eafa8586518819cddc9f13d7d721f00e4843ff9d6b00878b024a9368028bedcedb0f8ba9f75ba837bdf23c93d4a3257de45ba05995996821c862cd3c360bd39ef1c05ef3d64f3597688dafac2418f40bf97be693099854a05ab906a94640a395e1aec6abe7a91996896276b58a1fd55d8d2645ba1901f4514bb8af173e5e95bcb4b635ec2445e4b6205f711ab0cfbc3f8fbf8bfec533f746fd7acedf11b4a66f371a02f42d1f8f7c36a4bf5f100cfc665361a1d4e3b6cf3f1b51ce6df7543fc026d7015fb973f8921384fb921b219b7d59916168eb0d8db1150201941ebb608a9a34ac99df89371971f3921873041df22274e23ba378dbb14a1d67b865101fed96dd037492b7b73f0c8f2155f6b07de6dee4365065f71f9af7cfa7904e9ef5b6a417bb19c0edf5a58d90ac15d536df091e1e735ce641c7977e83455f0d4bfbce191f71c139a02ad09da5a71669a845986e5cd81903bc2fcf87667a77511271a22e400ee8518348357e594d94c0b9c80b738464393eb314c8eb9cacd422ad674b6bb3e86488850663a4ce9b996124515acb2b941db207ab42b2178e88838aefbe786d031e10409d0dde8a46e1f10afa41952adb8eca07f1785b7682ec2eaecf58cc5d2d6d8e41c86bb6190c316798b5f7bfcda275c61c3e65da4caa99dded9552e677bc97e9804878077af17b23430c7de12bd6f6ce103d8c79bbc761b94a0e98560c442370fae8b13e73fed4c6332d74ae4fadaf025ba3a3e3b91ca42be7ca07c84adf1c18e9d844c2256b2afe65354c55e7ac3bbc4c3700381ecf945bd57b4fd85cefde464cef8fd7ede5e16d83f770a20db982ff5632631d1251b00d443b0a8449dcbddc5bcc0b2a531a1487383b0782e3c42298c30202ff5f0cd0120cf8379a7629ee913c7d6feef0b230801c1eecf65a41fdf10297a9d11d9af6d275b2546246313ea3146f62e842b98cfa63f635673f76fdfa974f1c4b9a9f7180f5fd821c5cbc06ecae488f47b1a16d6300b556ffa37d22a039e884bac33031682e30a4f37ed4a20929070f68678cfa7ddf07e85af564281e4661ea8f6f5e7adf61d0faac9fdfeb743f46321d715bf5c1a0d3dbd73f6b694d0d54733f0777e10277b5166655baae53d50bb6ff5dfdd6a8314be5511c82eef8714aa3b6f9e0001085a980f7f9b4d7a647a0255b985706e7f2a40124a61dd8cc75b23957d377be6fb791e9b2eed408cba754ad47543a788a1c86d513d13e805c0c516d0d2d7d7227a84d3fc7dbbb12b346b4f14cfcb1b46c562fa08d5ef181de0232792171a29682d12fe7aa49d3056b475df44311dbe4bb05f6d139eaa69d63754e82ee1fa8fb2c943589952fb05dc8a3566c5fc6ffbb135badf57ebc8c97c90ed22ab381960a54d9c4815744c144e270180d09c1afd13db0aa5dd2849c8ab710a5deda647a1f2ea7488ad56baddddc131711b0eabc2a954a551d4e488c339afd7b50d0fac25eb3f3b1d0a81db4678202954886a2863e50232a5e8eb82ce53c72f0566841ca10c724621cd1322b80b776091e31868bccc5785254adaa93c3dde4bffe7e3fbc520fcde4247e2dda42dccedd33be150140a1d669ca760d2cf52222f042a518a0486dfe716d76dfd363573eb2d012dee8b23cad281c6f85f013cb16a8543433ad75afec14d50585ca6077e6a44b2ecbb7c70d19dd42114c5f5391c193b5fa492848e48760f3e858a2f3521fa0c8ccee73d4d7a051b7bac09d8e91f8355f591f8555f1b93dfc673e61cebc9a7bf1327baaac3fea44ce49e958820e593695b06574feb493fea7bcd7464747ae2f16c0648ed9f285d72e82e5c178a1de77f918681a5161333e5612167fc70c585da49d32cee28ef9905efade611117a76279fc791416ad88c723f289d116917e1a9931cb3f8b8b0bcce64cab7006a793340c369b9011700e352b358fdc9798e2c7c67d4891a1d900c9d84aa435481c62d2919f360b4fbab4e2424dc11bcafe70fa94926bd07f9ffeb3d3b8411d9d87193d04f39142db168d435ec83bd3c3d0f8da76694c6c770eff8fd9588a369e3e299b37e221bb48d382ea44cacd11021597fabb4cb050a1b9baacd7e8c99f96674d3192b565f010e27747b9cc1d8dafb000000000000000000000000000000000000000000070d11141822", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "622db4b1c15f5f5ee55e9911432b2a58caa5bd242a6f38a9e2d9cac83db4a3991aef762a57ef2951187e5b0c03c0fad65f5b3ac69243a5833816f00795d125c5ab25129464d3a77dd145b957a5420f9e8bfcb6d639b4e5a46a101fb96473d2e2bd9d9c479141958fa8d52a3e63d3ea668b9268ae24e291a494caa1eda447426cf391fcc84d076c2df829b2bfb5fe7fb2182460684f94340ad41e7b7f5660a5c6d9f6e38adfe7086c45fef3dd5e66f7d7e032236774c52f8c06f3008b183d979d06fc966e34f526ff8efd86d7dffec406f880471cd5af32134fcaac7cd8caa23cec42e589c7e859db26aea52a732bb48d066280677442b640889cbefb4a6865500d44785ab33c8e74eb82d13e05a87897c022ac9614a41f04e4d8a4c2b22216cfc10fc3b8b91d63fa1b74ce44983a04c9fea3e77897c1e3d1fd08a2fde8e68cfc31d57f7f156da2d33062a61fc96db4cc7a7cbf27b91bd93a56347a672f0f68bf44b9a8ba6e249e383644a2487784b5915d64849b2f4644d195dea5c2fc999a8eda3cf68b750960cde5056750a3fdcaae514747a4bcc88fa4e1abf63d5da5975800e97510fe450715c03d5029d544cf9d41c59a05ae9157cba73c9f02ed8296dc1bcf8de8d0f992b0e043e1b0eb83beb0418bfefc26de68867a35b409be773dc51033da3aa784fef4121006296c208c137d0ffc48d3ce9e9e6a19c48b390d4c6ddab012eb919e5630a273ae6ad1c9faaf9e83e93da948e1691084df45e239afaed3f1d9731fec22a91ab9e5bb364f000c171bbb6ae088382fb1adcfc354e94393ea0db44db1e30acbe52a49db521a8ac79c16b7559d608f02ddd8ee514d9e2ccf0740c19e6107acb72657002979af90c2d1d0f44bbd862050405b7c9afd5b154c68a5653c3a984f4d14d06cfdc2043a2226e5f1d8bcbfdbea856dcebf7aa3759c38b1367dce410044a57058360dbd279169dbc1d5e8b7940a857968bfe0c7a5db696a23806070a69bdab657d3217b96cda7cec1a274629bd2f4c88858dbb0446df2cd895ec57521becd5177c826ad0f1ad54ccdc5c3a63456a7cb39fc7017df70390f55c96502b66ea69d7c568546b24532f862db89a0c3be684b8a3b0ca52ddef8482ec7282919dfd326deca6a4a466dce14c629dcfed5a50118e870ac6a807edb4deb08a253fa7bfb968814e02f820cf785b927db5a00d04dc51b4ec9af2448d9651d8ebbfcfac601bc1d0ce4cdd91be785461cbf8590aa1fc8fe9994eee45ac506b5e87d693fbbec2b0f09144118bf2bf38d7e996b6d40a51b8585322e2b31e386ab45c03ff843a04ba987fe5ad426dfd291019100f84ee42b399b0d93ce8d6d1f6b0c0eba3cf3a9f8206aca86e50ed517f07246517d6d434e5918e96b1b0cc9506ac9cd8fc12b9afcd49c9289a0b28376134a4ccf9aa89086cc2a4997729ac99a8157eec6f1e1264d60ef4a0c07bfbb945e6d7a514366a036dc28d1b934a8aef657319a9f199a14bfb4e452b990825fb95987c0046855d6ea7314218dd4837fd23652cb6494a5a989ca5f297daa01132775bf3e6a08a717a2f17638082e499e6cd859ef564949e15900701fb83f8afe9f9f2cc9a6b9e5eb363651c052edc02e973b4ad4a4a51faee71d3142a67fdf20dd7b77344d0dfa04643a6a921f03436dac9b245fa6065f2b23e7d3f0b1f9acd61ef6d68d939802ba0d63cbbf3d7d8c9d68dc40ae395fefafe624e76f51051fd01b53bb881b99929d09e7bd718c6750e179c3e72cc53e5cf820c1c8b0ca8459dd103deae592ee59b1fd40c408bbf5aaf3f9daba04441cfe039b7c03e52a582ad8970862e14a00c9a637be2078b8550079ddcbf14858d98e69ce375f1d40866c2c3d5abee04b06330bc764b958a0e85981afab11ba6cd8cd4b3cfa319444013daaf0ed9bccd64ac258357622e9b21e17a06d863ae9950fbf8d6118eb4371e04194b746a9efb5e1a3313f63f7d4b9b06893ac53754bb6fe323e12ef760c05c3c4fe3a03db518ba03447f89982f3f57a51a556edde0e578ced15f28779d3cee4950b0da6ad35bf4fdded4f22f0c409956ddae098553414ba2faabc4fe3cd550abe9d4b9f8d04468787a2ca50b47ca67b43eab5557a6652fc722c8790ceb93e5d494872843976fd5593d2030a3979d508228271f4870c9cd517e69bc2cd4624a3ed7d4959061a3e26319cf5bf9f4645cabdee1f8f03966937614b7a94ab7ca28ddd15f1a267d1a4caaac5e2a4b0079092e8ce9507f524044537c520b84ce0eba7af9b1c3a056209fe16ac15ea4e3c1a3837f08ce2b86c135a4a1ff78665ad76df0f0da877761fa107e86a23ccc08ef5239a365dbe1ae3e33ce531523d188438296bad2fffa43491d8c164404ca5a22e01cd2d2828d89b0e3333997f7166bc4643468cbd392546a0f015454b8cbe5a82bc92fe168c05124e809aaff0bc946295b8a12e25d2899a95e4fd57733eb0ac67c552aa370cfd7c2703aba864544f651f0f4ac9d0bc48bb169ace6435df0a9859d59f5ffec4f0226291ccb1baea61dfb2f7e14777aa6901b6591bd15fd7f6ee70be9fae2892bf8bdcafe7656289c3403f6b29bc3bf9a977f562034cce76505d750de6502103098f893c5a0e56409b4117795b85d784bae1a00c00c39f5ae9f4f5dd9332dcb293ea2e95f2456b1f3e47d65c00418b24af7ea8f250af298a58248e01a504f355affc3c65edec93a8eed6945033aae1db204dc0a9fa46924ec4c891bcb3", - "tests": [ - { - "tcId": 77, - "comment": "expand_a requires 23103 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "8f46c68b4cdf1ec20f57a26aede6e7fa768ffe1caf2ad14dddb070af1bffcdf53e996a4c5f009b21400f21a51b90ec6d5dba942d359af0a5feebc18315dc85dd4b5b7f4bf0c1298a6b38472cb7adeedbba5367a7bb86776f2405c665f2d1c77ec94f9ed7ed3f0e025c46b158ff66fb62fe7220ffd466da07b099f4e32b7be99b39bfce7cb526f0c1aef67b63c04e21fb93c0fd44d3cbd1edf4c437af20e917d7859be5398fad2ac8bf6c422a3674c2924d01ecaca88bde6b02a92d4ca31f559075a78a011f1ff334f8d33ee27ca9a27202bb1d045c15607202fea700f737cc5db44efa4448f469c07c5c690eb5d244dd7279fdd7a5cee75c2234d176c9a1aeb337803a432c563443610a646335e1a08e26baa26cd52d836e1c3309211b071d552ab3daeb0e8bc42fbb4d5877fb3814da62306313474d5e86ed9808dcc6f0c302b2f9811fc18eda56d9e3c44fc01940510fd2ed83b85300b69170290bd07596f79fad3ede82a6b8b47f31dd7e8a04705dcaa44caa717bcfa288d2662b2ba98d3aaf930a9aaa59389e5d153a4d5692dd92c5189136ee81934b81b7da6ab8c4c1d0b80efd312be2344153cb03395eec9c808a7be202ff4f51ff0021fe30c9f7be4d1f0e53b24f67c06d057810d9a072c5394b49f500a0523e8d1fd2c3e0a4441b3132ee116858d78a9b4c7987dde46e10ef202c2a5b793a3c4fce39d776cc52c6fdbe582a3fd9a09f9916d14750341e3d5fca75b2466b5e6ad5d5b577f154907ce98b5b1e6060e0e307ea899b3911e4978070cb76728c82e91a1334d61d9939a601501fcbf75d6dac20ea9bd32cb2ced147a4a51df0ddefddea0116264bdf9abb8074a6cafa2a6ebe4a6cc48eb0a9d9cc55f14d7f2e526ca6109ab213270303a0ca3b1490a6bd056358c0e741093db14fc01cf6807d8cc5596b217e61319c72aaa18dde047c3a04b4147ca127bba41218e1ed529f534d71c442149197a5ab715e427ac79f8758e37f623b73ef6a2b55207aa7ade98ef5a4f6989bf4330cfae3e3651444d5b71001dd5aae4432980b555bbb931c0fd9f5abd1af22a4a1d2e2d117d3b8f63474dca28f96049b30548ddab448872f4dfbfec63555292a0f90d54b80c5e3dd8c5c785c3e4d00c643bc8511fbb9aa716caa06b14041f9c4bedd6c6d339220a4724079e504454dffc5c9d299c773e14da80ee3d99824b6ebd93aa71d4201492c04bf2056fbb430acc0d1d425006e5b232b22d5fb1484f25181198e81e4b24fede7c0c498d55f451f2777ccf24778493ae2e0f81b1077cceaf0c0d012c96ae8b1ac5bc3a3f8aa1f361b5beeef3acbd95b7a971021a9aad77a82e059cfcc6d0bcd799121b729f12d2cc8274496bf854bdbfd8e932942e39f5b7906b6a96f4effa903c0bce837160694b2a97ec89c1b0f7f35d16a8995f831b1e5162649e711b71252822ae131a5cc23e7be487be8b1f3b5ba359216e7273adec9bccf6c15a1a3f4c96476b90f11cf94b6d04ff59e6bb19be14f35bf395d7faf85cff288842546efd8ce42b5a29a6fa620581b8dcc51dc2610cd08cccd4f141595daca8cef416cad7907248c58d9327e3d9556bc6be6119bb983cb1faa2b492456b075c7e5aae4e311b61821f51f3c3ed0749852c3788ccd3441beb9ee6cfeecdfdad4d7d4461702e2e1cb6916ae9a9ec096b7775ca6cbb13604419acd40f4b35c7429b8700c8c0a7f6243f5cfa3aa739b713974ef74f84788452ddf5be5d078cd80a2290fd9992ebcb136bc8978372b622bbaecfff00c1c6907ca231aa1441f36697bb29ee93d5a5bc951e9a7893e4202d3cb5dd6324d7db70976ad7666da4e94941862962d3af783ab2bd173c536f999f5627cb7cb7ecda596e65dad4de7668a976b0ce6698bbba26461d78ef1bdc0267c761b708435441ba21dcac62ac6cb1db54499fbe2b441f927b993649c110c00a947be9381f3235861460ffaaaf0b353ce002b81a957e39291fc4f65fdd791281a30f4ca32c297f2c6fb8327454751866239cf4772bdf79368dd99d28c61c7209aaa13297e0fa958ab9a2623c80e779c0745c10f42e792dbcc18099a27a99e9f8a0d389e191609aaf3ad9c3a6661cd7611bb778f706b74a834aa662e70bffad896846faf86a052e6372aae1058bb9dc96b1bd9111b5b1eb47e3badb26f7396642764f3144a7e9f5a903d67f1ec74e8806fc48e354ff37a138a47b3b4c8813d7a7992aba5310a439a1d90848487020c0983b48c5ee97ec658eef7bc93b030b57f16961ec655fef8408a9132ef76016e21dbbde30251501a701b9310ef387ad88c2281a7634b381c10050c50a43d9529c923a81d9b3929727e2b499fd9738d75cfb239c6ea3e94b5951c708d18102ff06aad9d20a219cd867a4c8e7e8e1ef7c84f67217c148f44b422714a381d33f72755ef056f53098cc8fd9877cd6742b2f77b4f2dba9ac9045c17515858baaf3e34f4d74a6e96e8d4fe661211674a68e0912b7c0b4b80811ca60c4518350b3f54df34db7f69de214dae9e14abcaa01c5f28ffff384b438f46547009a8f7e55511e60f2850f75bd337f0045ee00c51a51e655719ea4da79e9a60eb2397008701becdc5a83619c7f90667ee024c44ad392cabc6d7799fa59c8f6125b85284aa48cc7537ec0ef17e83deeb1c99477ebfcb3d51df7443aa692f7319933297a1de00dd310a055611efe998e1281ba0a448521fa0c63df5e7082de1ffc0534f85901fb320211f46f439f13314800826ee72f68c76fe82e45d2f19d9722d017ed44eb14a8a9864c79f29c1082054badbd6249fe8f93f8e9fc65bb3cd1af8aafbbf56964074d782564adb1c25ed8b08f8430bc16836176422fba4e7ff1684a61d881c020d4e659429b48f9f3e64f16d24021d6f89add4c75d237fa9043d32cc27784b7c08844826178b9dddf6fb823aeef3e8fd5aafe581c393c2dfd041f8148aee08a974d5318c746c22d9e4179eb56abdc72db1c6118fff4d9d8d6cb446ee19a07b7fab8df403880aee09dca1cda2a39ec10d5a78457e3aa3cff48468170094ad22d30a2d44428cfe7467a4ec539871cefcd548c3062480b2ed2b6e7a6bd6110aeef4166cd0b45dda83aea875b3ba10a9b3aaa9726f3c782751e85550d144231853037544f39d5dd039234cb42fa88fc0e5f1e0b66f068fd90523ed6e1741679035a7e8419da10a7604b13858ec59be5e5ed7d298e29bee15eb9d66e91ea004d80c261b09474d3f32b7e6bf321fa980786bdc374134e9a5b64c4549cff6d0f073a9675a27a118dc12d5b745da2b3d6615280802756895b6efef4c3dae82e30b3c275b1d34aa55c9f650acf2b727c7e1ce304e1f966dc549a785952135073c3dcb9216885a7460fafdcf7b5fba53789268a8a21005a877962eac88805d7e1286cbb26e34351c1ecfd808a9ebecd2893108fcda6a39eabc133d7fb015ab978ee2ce4f6c6f132e11eb24a82e4e43759ad1ba10dbddcb758a54cb1cc9ecd955bc7f43cb6144423ba5d62d6296c89b1992751dcfd37523b647ac22f468b37120ccc461fe4bc817796e835d0f47a351e2c18769a25c988c7dab905001c8de47aef0e75c7d5b1c299db472600112f656d3740c31ca5017f4624803ee5baeb4ad4974a04be45067e747e2071c66f1a2e607dd11810c78b48fd7249398b8b5ec18e494811e68502872a0a9862d8d9f66122533f0e4893956aac7d98c3f2fb04ea93d8a0f7ddacd0072ec18b54bd814a8ded374d26d69bd7d277422746fb8371828a8e8ff398b5230a2fec8f1ac7a750fc2c6eb6c9341a5bedf7248c796f5b87d9f3449e0f0b3a32d8e283812e98154cf002a02a744f247a20cea768d283ff113466f4775e1170b7395571873b84d5a7e1f7c06a657ed9a09a8789fbebc4fe651735cd5e42a08a5adddaf9827c33078a933b74bfc83a3d2e9ac0386693a6b5eb623a223df33d5c10df6ee4a1616160bedbff3710726f7b21d11dbc7a8a59c52a57e1dc17f914fc3c6d21bb1740faaf09ce4dfc887970cb66be3c9e154e7e554a744793b704593e40550987d60a589970f9756f7e6e4d7fee9cf673f0bd40b9899de4d8ce43c14c1a0def773cdc33dd81147a10fe6557f09e0a863e369d7374ff934563f84ebcd75267822b71acf5354efaf5d35d6299fa186ae28f6092069483b19db0396e008761203a1fa92d8e7a844ed237f3ed30c8c56cbd48a29815d02acbe917fcf2212a69f543a132204a48e8c692f78f039cdc63fa17ac2688c6d4ad716bb56671876e5f2a9036e9be1e2ca1405957e428928aa938bb96a9985d9a32b94b955acc5d4314300b10057d5ea099c65f0e0098fe5edf08b8cd43e93961c5ab94cee68f25a2b17adb7234e88a9dc79ff8b72c9ee205d457c321514b7fd87f482c0e8fe0b6294996527300a64d964d02438351caac5aeab1ee5c5be5bb38b605f974802579e0d34af06a3d5b4a0156aaa1da8e35d694bd4be6908974f5f9af626d16efb52b01d5a81487b669c23dadd71461144ac251e359e6f3ecb9475b2f89b837d1c434d590618c961cad556e5f98110fdf019e813a6bf20925167ee010144597fe8f87bb1dd1b888d8fa5fa032123455c7da5abbd2633527eadcae5f4041835738d00000000000000000000000000000000000006090f182025", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "2828f4f44461a839e748b07acc053c9b0241f7b1425f9c742019c17078ffa036e967faa39da0636d9399bb909039818275a62ca07ff9bccb028accb7ba906e18c9135147fb27858bd224a228c306543bc21092a59881cd6653318f824e59cb7708d34271b38ef517d9a9ae6d37f07bfbecdc05ad59da3247ba2e8587a3b09feeee4fc630c81973cbf455e60a7b2e521350c3e4044b0ae5eca91f1ea9d9f17018021153c5e7ca6b9f9ccba19e093527bf8e1acfeffbac125bdc314267372bd0f2c2fb064e990f367815fa5bc21f98c715c8dc86d36ae7efba6d75f9f5e332df3c6127ac5263647536f6646996f27930318f4db8da6484c9cfa366080d0ea01f019f5b0da25794bea98744ec505d02ee671d6a9e311ebb91b51e1ce1c59bf70714a0b7fb7e25cc0b6e86d661346b6921a96de4fe1de9b788e18791f6e9597f577145ae7c9b39b8c10643edce55bd8db7baa631a0ce1e52b1c67c34761b4d045da421538e1efb7e9249da2590dd52f05102691dd529a3ada382ba255730e3f594104e9e2f9bd9a0d012f446905d6eed766ac4cb3094e5c40b5e2e12eaacb433a1f4593b74a0e8c5033c6846c7ac866d756d27e07b4f771d2d3f45dca0cd9fc1f50b24c50181dfa64530162e4513a1dc0d3fa73fbdc5a9f2a73a032f59122dc818f064224f4687ad32d27357d6f0b3c392eddb2d25de43bae084da96bb985e5521452f056ac139b81167285164ab462aa2c31a3224903f72be0cad6f1de86150c651a2319cc132e55b1517015522689b7fbebe00ebb9bbf494680ef954c97349f87dc4b3a67de92da831f6b2072e294b0d5191be06feb54e36b9c7f8fde964754498174096ab1bbca6dade876c8166e670196f507e6127d9c7ee4d5195bca2940c27375d41197552eba03ac9a2ed59facd73a322f7d701f95433519543a0701c2be58e5505632e63fd831cb92309dd23bf9757ffef9bd618cf90eb184e11c51e139a9ecae0e009927eb64881519b035c81370d602fba3eb43f5c8a031cf093b634e28028c97b5d7ea962564639d247eaeb8d4f5deab4b587b87b8337f7b9dc980db721b7d20e25043eb856147a429ee22655ebfc3b54b4d7d957b567047065de5ea915f3259b0cbcb4e46dc4036d9d4ed8506f0ce2ff7be09f0eb37e6b1f3743eef7bef637c2619ec5e75c232b4dfb9a4a860f7f808cf0b0fb3d0981a800ce83a26282e02bda97c360e7b084c727d6b5ee5aa87a938fb6f714ffd0762790e8333991d057765f4b9cbf26f5b8c2ea993f6517e807749f342cd1623da8003975235fd54517fcad9fa2f345d1193bd35132d82a33a43b344a1e1a302a96b318ba0b28f21c99c940a20cf2bc3dd7d4d8df7e3fc47ca751be64ebc05703229b7e74551f5e57617ff0dd8ad6c2024ad182e9998a3dc67a6ed0bade4872c066c54ee822cbb305238547ff4de783375b6d560d3c1bf818ea5c208cbc6a8d8cf77eac9a8b6e80af4c434d0fb2f42083c75b1fe0d609be047d182b637ee37c74fef271a815a08174cd070ff39c660473b054c1b9fdac90c318a6e5b1ca8918980e347eb077b3595813a12bd1b4c9c6f8d902375078b5ab0fa33d8152789e86150f0df469b4808b2fbbc9f18e4434b9b91b61bb4fdc39ef06630934a4bfc2b175f065f94231bdd95c419453fe4fbbc9d7dbb909895d04d2f2d1e2c2f3529a900e4b347060a0fc469134e1eeb78d56dcac2964f9d32aa74231747583f4f3782391c828bc35d3928c7a694085ed63f7c83792ef85be85ba88fd6e6fed04640584def57fe1e9c8ca247c5e53e984bb2df9de8ee4a72a5d05d5db46f261315b195503e8cbbe45a9f97836997af252212aba12e5da4a7fea8e29115a0e4f05bbfed93730709ff43f378100059f28e6dde2f4b210890e5c25404b1c5410a8c32c9ab626dbecbf90cdeaa7b76248d477125f9a73a9b41fceb547675d4ac3f9aa98027fc9666f0267cb13a8199ad802595f53d4f49b18e31b1c35d2a3cae174c46d9810995ec4952739e14dc3ba4724261d17e24f6f25301d271ab952e0db0692b5dcf2875132debad65898026ca7323097cde7ec8338934bdcdba4d8d9e1cdf1399d01e6967263c78df1df84c8fdec5bae81c01de78f02977beaf958d80dab2fe1a9d70f6de7318e99cad4cfec15acdcf06570e98589c7d072c52673edafb33140f4c6ce3adae1f226e606ec0c3dd7341942cc1925e6f0c5c0f9ab40c27e5b3b69fecdb723908a5617cec70d5057e6f7516a39d747f5eb197b903758ab2947f777a34f7d6f7d0e6cb6da17069795204c90e9aaab93ce22a9c3166a7900b86dbae141fbfa876a454e530fcd1faa182e962a3d9b671b07c18c46f222b98058b96a143f188b2114a44a7b9c41c817e1539dbdc4626d5e88853f33cb8e0920db5e14d2d776bf8649a71a935e50c62c237c004face4d1ad054b831bc4a07d3aaa92ab77e5eff1a2f9776bf57287970b9ed9f1c1bba3a033837f8e0ef58b57ab3c2849187b65f2c84d299731cde4d01cf91c9c53f45dd909377f400dc9a490fafac0410724388fb8f3621d794fccd268971bd46954c51122ac725e9924339bf3f6e5bbc9a200d110adccd91942dec6ec0c4012aad5aafaa9a7df777b1d975c37a7971e7cca1948e1d16b86f8d0f4945b4fc7409694813c5dd0f6890250b6904738a5404af68e5d35d4fe7059d5c48a8b906548c94fcf76568bd562f4ea06e10bbf349142dde245bc8bdd8673e5ac", - "tests": [ - { - "tcId": 78, - "comment": "rej_bounded_poly (sample_uniform_eta) requires 3 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "45c74c2f9d98d9343257f12d6ca0e80a4fdf0923081fed79412e4a468c0c1cab92c9d537ddbaddeee90b1da792c2288704605e285af67a1aca821c7115c34df21b0545ea4f8d670ac7a973a23cacdd150ff8f76e7957b98104cb90c43859359189d5c82b50e13f0328305676ecfe7e98a07f4d9a91482901fa3d6cd0b704199ca72542fbbe328eea284049ee95153b3370314c3275d76e81f4fa1a8a0324ccbbc23f1a98a511dc507d23352ec119b93b1c0b58b97ee71ed3a7b0b0783dec92e3834c7a1a0054f6b3f42d97e5fe5999659ad854fc859530b50af080b445187493cdd6094a0cd8253d24609bdba9ef471c03e620800938928b5a4a28aded028493867969096cf9d8378cc7930de9afcb94200e6bdd216ca5d5bc877d5607e633a519274ba5d79c22ff71cf54af14ed7bf0ed6b0570f652ac48fc268328cf822d4d30402eea1d506142d4743ea19ad82ef2c62e0f9e48eb104cc47db132ea3e94cf8fb13ba56fe098b96b9ec4d180f9cf204a62e58d11f640d311640cf1e393e8578545826dbb387a6c22596bbb0ccadc3de519143a4c253c07a878189693c26bb06afc8616fbefea67a390d5008c61c3eb67406553f21e340d4c950bb5409646a07f2627a7d0cf96a4310455b8366ae34e13131cd8bc39b184830a47092197525747840fd3f35bb47b308174d296a67e132f73bef36346b08db87234cd7a61df9452bc9689bd2f2fde66b48c74fca4d26e12d1c4613ae1198bd447d917d6a6f117e3ce42a38fa2ae2e554a8793f575387ad49a902544e20e1acf8973ad586c659b80f66244a658793186e2241469751de168386247b42c1f573eea4b9a57a475111d37a3724997a1423392024200f4adcd251021e3af6c948278e198cbeb5562d26ba2ebb9b0e212d34d54d9c618e222c7f60a17a634a7682036d3e467b737291ae3175f280459207210822ebf74c080449ab87fee72f9574efb116a0b1bdb9aa22bdd47d17a21aac5bedf9a3a80a56ee4dc57a079fcd3d7c33608e64b7a87482d2e1b061026df6eee3463a48bc1afaaa61a6087aee5864fe38a968b4c0e10fd839431cdfe03115f158a25fa73dc945d63743e3a9477afc388697c6291ab09d5e145f2ee9731c0de90e84ed97e48a5eea05405ae0d9a12faf82119ea5c2dce8cc118b7d584e3ff296f0bbbc057cae3be7235049bba5fa0887e6915758ae2fad31d7d26e679ceb4642a316694b3e26dd2a39066ba783d1f4e217fd9dbda82ad0ebbdc5c6c7a83ea4142874ee6fa31ce1f74f1621cf9775fc139f7819a386019d0138c82b5456b3de55f0086962f1388bd6a5ae7dc2e259d4fd7aa2393598baffb321884810e5c43e158286f031f867865ce4f2b776f3a3832419bc347570c0fcbc5beaf6a939ba995ae7ec35acf101ceef7d4e415d5abd977392794d19326f695acdee4d32b0b2545f70e03154c5ff5f5ed9baebbd37a93b3a926ec96ff2f010051fc11e2e560ef718ce7f9e55b4ec9e7fb1c000e190f970310e577b72b5d0f08a52175b466ba44e06d82b2b9a14d33eecc2d7aac8a5bb1e50a91a13dc3a7b80c077ac7e7be88ac5272adbf3e361a0d2ce87fbb860c4a4016204c7530104048242ddd11ccd78ba00c064afb51fdca447e613129a8e5e568aef7b13bf06d3990bcfdcf74830109177bf46f9beddc6b4e01aa1ae3cd9137dcb47e711e7b01319267874a9c8febcd1ab4f3abe7b4ba088029af6e4714c8e1231b9d819b7f3843673da5319299036664608278175c781a0517d50ba48c3bc7d480195236a1259ce8e4ca9fec41c96a3b2ac1a4314a2739e57368ac030b85d447090cefe997d61ed2e44a879f947541608d7296a255e3b07443110201f11c227ebdabdc04990f9cb46967de0b7448c9c2caed883f849115d9a7904fa2844b1fc4c81fffaa4cb6c93ff69f0012920d540c1c67f19e9e90c60bfa285b19a92930bbdecf2f12e257c2c0d6aa880f7609dbdfcc135f8244e2b209180541c56b8a870915c96d9f6110cb6bc8ef6485cb5d4413ea2e80a42aaa4cdba7f04815ee37af3809032a0651b897d977c7d2ee5ecee346f0d9e7848780cc90f5fdffd8c23bf3f73f0b3e53b385556b23a988afc86f99a9a85815051fef4b9bfa88ce55232dcee5312b1315d7b13552939b4c7964fae29abfe83236077e600a2a02159c52b90146ccc65881db5c900101fd48150778ff7b993afdafe2a03e5841c736264b9928d1ed7aeb7036180d86a17136cd62b9d8d90bdecdf2707cb4606b350ac6121fec880659b5726fb8ed8923b342bd22a300a6df4bce9b4f70c79ccbdf7c42c9ed3c5cea4bbe3823031c44f710053740e55dfcb7c488f600cecf1b5c974dc6e483bd0205f56c2a3a674c49ad2da1ff9e37cfd8f059158a1b15c2e81ce26b83bf86712ae8718a58c58cbe10127147b5d3aeb92162b388366d779f8a126a3b5bee56902fbc1f6a449d74a7863a0b6037ca5ffbac5041bce68a2db29dd6bef264c7d6f244de69b10aea5c7bcaa379ef0c7ab47f1bacdc57925bcdc12457ef1e737111877411b74e1ef77491661ab00bb7d38f51160a90d4b500416ccd949aa17ccce7161c3dbb70769b4953adc3fe64a2e45f0fe204a3bcb37cb3b24ca07fa6c4239710129acf1d98c1922f8fd8aa8ddb207162a1b3dedc0e390a4893edbdb690d9aef686c64147cc718ded608c329eccffbe338dca3a36a4c4e4ed48160699db6b78e25e54d0b3e551c080f3c2bf5b6b78b951de81bcb9724b4c8c66d5cdbdc77292a7b7a82481febb65e90557b2effd9f253dfe7208e5e0cb0234b566dd33837a0b93bdfce7d3322b54a37e0058c93bcf66303d0ecd55f16c5c0c68d20363b8179d4ed96305fa632d489dfd64624c4042a6f0a57fcb1afa06db489a063a59b7740f71065214b542c22d1744b6dd1167ef35bd45ac047945df7b0f67e4e6d5b7aec57b07f0f74dc4922905168849fe4c5044ee65ac36bd6095d56db2c6ed1749af08e6ab80560aea4c736fe610e4b9ab6eb212c4eadf0b2895222d4e5bd289905199eb4566e0b2569055b6d6590d9a3e4f647b7366c8793327cc9462fa3bb4d9b7d3eb8ed43a5c1603e0917c2a4b55dbd20b40bdd84dd379e4c7c3e4e7880ff32769633870bc7ebc79d6396bef835afa39539a327891b9037030c75a46b274353a5ff2f1761999b6fb214158f337f0b098f8bd40a8c8a592abc004d5f8134053047412309bfcbc7faf5dfcc0f44e766d2c7e7f651ac468330bd301e21ffc863855dfccc385c83f3c024bfdb732f596cf945a9dc724f85eaa5adb2237b41b485954162890e71e23528db0a5aad3ad47b9389744599f96ff5c7189271ebd2c12ea16000f56e0d15f0362acd48a91e3863a1ca98318266c3d63555ad96f0d188e3275fca834c20ae62bd97308ccbfae323066015e3a33169d05f4ff5068a645b9ebb7aad64ffda44f9d0580560d23850177aef4ed42064de173a50f5bfb5e5bf6d9d39eaf8d565f342a8d9880118cc1d069480bbd6cd615383f85d2e495c4c33818b6106cd241e16cfefba1aaeb5f631423c1d8ae8e6553a3ac5e8a85687c243e0d4318162dcb2ffe2afc5b9d551a7a755efcb96113f1e9b596180c6bec210f9e36a81fa686f5073c573191aa23603a8067bd441cc9d46dfd55f6b1b2c36d4ad04d96fa326b05b7526e43dde99051549718a48361a40bfda5073b8c95c154741f901007740fb0e84059fb7d085408bfce226e0cd08e0361f9cbf4b257d109cac12aa86a122ea823bb4b6c13eb74237f9499799d73e8d244288776ab6e344dc2b6dab89b7e0f764cb849473a168cdb92411b0664d76841fe5dfe477fab40997ff18c13180512bddc04f74a9a0b24cadad0d969677e108d0d4c9cd878415186f958d49fbf04e2e446f362e8c2359d3d7799f7976e490fe3269afd2302bc7cd3d434fdadeb459ac76b5dfef29bbf84814d1cf21d4c374ea12fe34c4b9186c068d7075bb05d12e702c5fd6c7e6a7da986d9d65031bf3fc0a43aa546f06e46785d63f02e965e5ffdbaa9ea7a092e1a149d3eee256da5810e1f565372b5d96a899f15ac7bb97a2cf510539d110db26e98f20056188177b5eba1e017ed78f60acd6c8ef59502a8b94776699a6fc80191ade5007bfa62df60c63875153b2305a8f9a05ac662e485f4e7e9673ca8e85d306d651f37d06e860c8fc50ec6199916b72b711d4ca74d7c031f03fd41bb7405c684b136beed4110bec947ccf1b56578396fd88a70f14ba683bed84e70a72779f31d7ca3d9db73ad4133779ac7790bd7e378334badbe2a148b2de5f3277b1e0b2a1b2396b88f1dec7e49f94bb38ad9dd509fe23ed46c0830ab1f89f04d6986cc3a3b373ac9bc8a83a37847d87321df3f5cd6eaadab300c5316d8a59f8f9397c968f5f778450369bcf118ecf730392e2672a8980a6556852330acb3f76d195d95623cf419ff726172aa5df52d5163cf1681b9c4274b2257c2a247f5667923d214e0c79ee66b1f7d315273dc2b5ff41f3728a619ed0145dbf36c089710c55e5c2cdc2c8296489f817d7f7d0e6892e8128a0e3e0ba65d74b2d50826ec325359617b7eacf80a48679397b7d9e31a225276ce0e465b679cd1d5df0000000000000000000000000000000000000004070f171c24", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 79, - "comment": "expand_s requires 23 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "45c74c2f9d98d9343257f12d6ca0e80a4fdf0923081fed79412e4a468c0c1cab92c9d537ddbaddeee90b1da792c2288704605e285af67a1aca821c7115c34df21b0545ea4f8d670ac7a973a23cacdd150ff8f76e7957b98104cb90c43859359189d5c82b50e13f0328305676ecfe7e98a07f4d9a91482901fa3d6cd0b704199ca72542fbbe328eea284049ee95153b3370314c3275d76e81f4fa1a8a0324ccbbc23f1a98a511dc507d23352ec119b93b1c0b58b97ee71ed3a7b0b0783dec92e3834c7a1a0054f6b3f42d97e5fe5999659ad854fc859530b50af080b445187493cdd6094a0cd8253d24609bdba9ef471c03e620800938928b5a4a28aded028493867969096cf9d8378cc7930de9afcb94200e6bdd216ca5d5bc877d5607e633a519274ba5d79c22ff71cf54af14ed7bf0ed6b0570f652ac48fc268328cf822d4d30402eea1d506142d4743ea19ad82ef2c62e0f9e48eb104cc47db132ea3e94cf8fb13ba56fe098b96b9ec4d180f9cf204a62e58d11f640d311640cf1e393e8578545826dbb387a6c22596bbb0ccadc3de519143a4c253c07a878189693c26bb06afc8616fbefea67a390d5008c61c3eb67406553f21e340d4c950bb5409646a07f2627a7d0cf96a4310455b8366ae34e13131cd8bc39b184830a47092197525747840fd3f35bb47b308174d296a67e132f73bef36346b08db87234cd7a61df9452bc9689bd2f2fde66b48c74fca4d26e12d1c4613ae1198bd447d917d6a6f117e3ce42a38fa2ae2e554a8793f575387ad49a902544e20e1acf8973ad586c659b80f66244a658793186e2241469751de168386247b42c1f573eea4b9a57a475111d37a3724997a1423392024200f4adcd251021e3af6c948278e198cbeb5562d26ba2ebb9b0e212d34d54d9c618e222c7f60a17a634a7682036d3e467b737291ae3175f280459207210822ebf74c080449ab87fee72f9574efb116a0b1bdb9aa22bdd47d17a21aac5bedf9a3a80a56ee4dc57a079fcd3d7c33608e64b7a87482d2e1b061026df6eee3463a48bc1afaaa61a6087aee5864fe38a968b4c0e10fd839431cdfe03115f158a25fa73dc945d63743e3a9477afc388697c6291ab09d5e145f2ee9731c0de90e84ed97e48a5eea05405ae0d9a12faf82119ea5c2dce8cc118b7d584e3ff296f0bbbc057cae3be7235049bba5fa0887e6915758ae2fad31d7d26e679ceb4642a316694b3e26dd2a39066ba783d1f4e217fd9dbda82ad0ebbdc5c6c7a83ea4142874ee6fa31ce1f74f1621cf9775fc139f7819a386019d0138c82b5456b3de55f0086962f1388bd6a5ae7dc2e259d4fd7aa2393598baffb321884810e5c43e158286f031f867865ce4f2b776f3a3832419bc347570c0fcbc5beaf6a939ba995ae7ec35acf101ceef7d4e415d5abd977392794d19326f695acdee4d32b0b2545f70e03154c5ff5f5ed9baebbd37a93b3a926ec96ff2f010051fc11e2e560ef718ce7f9e55b4ec9e7fb1c000e190f970310e577b72b5d0f08a52175b466ba44e06d82b2b9a14d33eecc2d7aac8a5bb1e50a91a13dc3a7b80c077ac7e7be88ac5272adbf3e361a0d2ce87fbb860c4a4016204c7530104048242ddd11ccd78ba00c064afb51fdca447e613129a8e5e568aef7b13bf06d3990bcfdcf74830109177bf46f9beddc6b4e01aa1ae3cd9137dcb47e711e7b01319267874a9c8febcd1ab4f3abe7b4ba088029af6e4714c8e1231b9d819b7f3843673da5319299036664608278175c781a0517d50ba48c3bc7d480195236a1259ce8e4ca9fec41c96a3b2ac1a4314a2739e57368ac030b85d447090cefe997d61ed2e44a879f947541608d7296a255e3b07443110201f11c227ebdabdc04990f9cb46967de0b7448c9c2caed883f849115d9a7904fa2844b1fc4c81fffaa4cb6c93ff69f0012920d540c1c67f19e9e90c60bfa285b19a92930bbdecf2f12e257c2c0d6aa880f7609dbdfcc135f8244e2b209180541c56b8a870915c96d9f6110cb6bc8ef6485cb5d4413ea2e80a42aaa4cdba7f04815ee37af3809032a0651b897d977c7d2ee5ecee346f0d9e7848780cc90f5fdffd8c23bf3f73f0b3e53b385556b23a988afc86f99a9a85815051fef4b9bfa88ce55232dcee5312b1315d7b13552939b4c7964fae29abfe83236077e600a2a02159c52b90146ccc65881db5c900101fd48150778ff7b993afdafe2a03e5841c736264b9928d1ed7aeb7036180d86a17136cd62b9d8d90bdecdf2707cb4606b350ac6121fec880659b5726fb8ed8923b342bd22a300a6df4bce9b4f70c79ccbdf7c42c9ed3c5cea4bbe3823031c44f710053740e55dfcb7c488f600cecf1b5c974dc6e483bd0205f56c2a3a674c49ad2da1ff9e37cfd8f059158a1b15c2e81ce26b83bf86712ae8718a58c58cbe10127147b5d3aeb92162b388366d779f8a126a3b5bee56902fbc1f6a449d74a7863a0b6037ca5ffbac5041bce68a2db29dd6bef264c7d6f244de69b10aea5c7bcaa379ef0c7ab47f1bacdc57925bcdc12457ef1e737111877411b74e1ef77491661ab00bb7d38f51160a90d4b500416ccd949aa17ccce7161c3dbb70769b4953adc3fe64a2e45f0fe204a3bcb37cb3b24ca07fa6c4239710129acf1d98c1922f8fd8aa8ddb207162a1b3dedc0e390a4893edbdb690d9aef686c64147cc718ded608c329eccffbe338dca3a36a4c4e4ed48160699db6b78e25e54d0b3e551c080f3c2bf5b6b78b951de81bcb9724b4c8c66d5cdbdc77292a7b7a82481febb65e90557b2effd9f253dfe7208e5e0cb0234b566dd33837a0b93bdfce7d3322b54a37e0058c93bcf66303d0ecd55f16c5c0c68d20363b8179d4ed96305fa632d489dfd64624c4042a6f0a57fcb1afa06db489a063a59b7740f71065214b542c22d1744b6dd1167ef35bd45ac047945df7b0f67e4e6d5b7aec57b07f0f74dc4922905168849fe4c5044ee65ac36bd6095d56db2c6ed1749af08e6ab80560aea4c736fe610e4b9ab6eb212c4eadf0b2895222d4e5bd289905199eb4566e0b2569055b6d6590d9a3e4f647b7366c8793327cc9462fa3bb4d9b7d3eb8ed43a5c1603e0917c2a4b55dbd20b40bdd84dd379e4c7c3e4e7880ff32769633870bc7ebc79d6396bef835afa39539a327891b9037030c75a46b274353a5ff2f1761999b6fb214158f337f0b098f8bd40a8c8a592abc004d5f8134053047412309bfcbc7faf5dfcc0f44e766d2c7e7f651ac468330bd301e21ffc863855dfccc385c83f3c024bfdb732f596cf945a9dc724f85eaa5adb2237b41b485954162890e71e23528db0a5aad3ad47b9389744599f96ff5c7189271ebd2c12ea16000f56e0d15f0362acd48a91e3863a1ca98318266c3d63555ad96f0d188e3275fca834c20ae62bd97308ccbfae323066015e3a33169d05f4ff5068a645b9ebb7aad64ffda44f9d0580560d23850177aef4ed42064de173a50f5bfb5e5bf6d9d39eaf8d565f342a8d9880118cc1d069480bbd6cd615383f85d2e495c4c33818b6106cd241e16cfefba1aaeb5f631423c1d8ae8e6553a3ac5e8a85687c243e0d4318162dcb2ffe2afc5b9d551a7a755efcb96113f1e9b596180c6bec210f9e36a81fa686f5073c573191aa23603a8067bd441cc9d46dfd55f6b1b2c36d4ad04d96fa326b05b7526e43dde99051549718a48361a40bfda5073b8c95c154741f901007740fb0e84059fb7d085408bfce226e0cd08e0361f9cbf4b257d109cac12aa86a122ea823bb4b6c13eb74237f9499799d73e8d244288776ab6e344dc2b6dab89b7e0f764cb849473a168cdb92411b0664d76841fe5dfe477fab40997ff18c13180512bddc04f74a9a0b24cadad0d969677e108d0d4c9cd878415186f958d49fbf04e2e446f362e8c2359d3d7799f7976e490fe3269afd2302bc7cd3d434fdadeb459ac76b5dfef29bbf84814d1cf21d4c374ea12fe34c4b9186c068d7075bb05d12e702c5fd6c7e6a7da986d9d65031bf3fc0a43aa546f06e46785d63f02e965e5ffdbaa9ea7a092e1a149d3eee256da5810e1f565372b5d96a899f15ac7bb97a2cf510539d110db26e98f20056188177b5eba1e017ed78f60acd6c8ef59502a8b94776699a6fc80191ade5007bfa62df60c63875153b2305a8f9a05ac662e485f4e7e9673ca8e85d306d651f37d06e860c8fc50ec6199916b72b711d4ca74d7c031f03fd41bb7405c684b136beed4110bec947ccf1b56578396fd88a70f14ba683bed84e70a72779f31d7ca3d9db73ad4133779ac7790bd7e378334badbe2a148b2de5f3277b1e0b2a1b2396b88f1dec7e49f94bb38ad9dd509fe23ed46c0830ab1f89f04d6986cc3a3b373ac9bc8a83a37847d87321df3f5cd6eaadab300c5316d8a59f8f9397c968f5f778450369bcf118ecf730392e2672a8980a6556852330acb3f76d195d95623cf419ff726172aa5df52d5163cf1681b9c4274b2257c2a247f5667923d214e0c79ee66b1f7d315273dc2b5ff41f3728a619ed0145dbf36c089710c55e5c2cdc2c8296489f817d7f7d0e6892e8128a0e3e0ba65d74b2d50826ec325359617b7eacf80a48679397b7d9e31a225276ce0e465b679cd1d5df0000000000000000000000000000000000000004070f171c24", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "fc9fbcbb96f54d5f1b2b71d060404538ee428f6785040c54adb8716adde1cb1fd35a18e25a3dcdcfcb36f67bbd5398dbd1e41d43e2da3d92f35a894168c5829e0e9e9ec957c6e64c0e2c90bb10402b80c16860a20e5c0f5cfb31e98fb965d79c6dbb5a92a76e0cd2e8e5bf89bd8431075d87d944f70d1d60ef39eeacb38950c3f3ea9c9e036beb99453beb674ef399472d2602b40d2681474a0f86f9322008f7ba074306c65888fb75076f2588cc828e03f4a20c6a86190705bb16d1b01f33fda71defb96cca68128d87ad616507e67f9abf5e1f4b893e6223cf9643e9bce85a60253ade53ce2f6483594507fb27bba13867cd5afeb36dea5d2d847e0d1de2c8a21465e435b427b9a21094844e4f9e386b8da5b7abbf642cad70380c2daa355a2ab183afa6412597a0d85a3b310ec11a2055a56771f6dabb00371f3a29d3a282ac8b1ee1e46fd31ccc98943d93f95c1f7b0b41c49b8c00bb229fd5c468fe47724e5c44cd90cac417c70c260cda880ce774aef25749616b941f4d3b394e58b752235e0824962d7d003457828a1d5c1549d3c496cbfe90950b780b12de7b976866edf29521f993fe3e93b189cb86551693e8016cd0147a4b6af60196779f4a916afebe71898308ba45712c593ace59eb006254a01eb76d48b9fd653e662b32435b8b5e71cdf77768b9c42f5a75f959f59a03fed130ab2c24eb34b0d41ced62726c7ab160a588007bae6e170c558908db0cab61933bfa840031cd131ac541a3484079ae77a8d4a4eefc8b72f952c0fb22352751507d311844439b9287272dc73b7b836ed85147f40871d05b9904c32389afaf94b84643c5449dc04f9a82f276fd50cfceff05e2f1dcba87d3ebfda747cf04e46da976f5864de1ea500a4ab58e7027977982fa46be9c8e565e5376733b706b01447a8bd2d80b766804e663a4f6cf58e4377346420eca7e757f6b28dbbe8e05f251ad58c61350d283de73be982d7c60250e4203a44e97849f6921238870f772459421cf223439dbaf21bae645d04b572e0884a6c8248b780a1df734b600e1ed6723d15d145b1476d11b36a337bcfe14e85354eb275d43bdfc62c242e2498f2263416d9de4fa7bad8512f14cd1cc964c9471094514ce7077d2dd2c45195dec402fbf49c63f9abcacb2e8eac10bcbb7b2312397f4ea03f70b390490592fc2b41464c48ca6dcc333be960178534b099aadf9bafcea4a5b74e1cb2aba6c13a57d05a4f2ab3002294565e02014254fb3b6f3ede1b2cf9315185e7c07dc82c74656d87121612b456b03c5eb93f1a81d8ec0eae7630937a2476af4b35fd07e61469881a2f7c0a1d56d299ee54455444a431a93e8e368553b7063c695076891e7532f29ee20de04ae37891dd3343e7445586dbba4c31a8723e1ac02c786c5e74171884217bc517838facccfde8453c62f719887425cf35068b126f5d389f394203cd377273e984bc4e9aa5b747bdbaf7e4b7607b77b0ec95e931d3e7661e98086a6e9975b72703034523884201cd6aa668eed0513bbabc6c3bd044c32fcd4aafa319041d07f7991bce70c3fb7a43dacaf7b5b58e624d36dc545d0a198ad8f03bea8363f61bc639186c497a857a85521647d856b64209bdf9311fb5d16ebdb9522345561c8f526bf106c107bc6f97fb93c98c3e5dd239ddbf8e736e936a2df93a863457889caa12cc64489b7561a469b9208873f766b57844f60aae913a27233bad42b5bde93c0544d9b52b3b45a90ce5aa67021bb1f8d35b67626ccbea718a42b3a5fa867ce53218bd48509087c67bb3e452b7e4e3aafafe7f1588fb653cf045a4ea5114806f5108fbe3410956adb1348761e6c5ce8f58b276ced2d721bfacae09c67f41ed9f00749f8a63aa9c367669980f2415cad8983691e69fb588ddda462d0109f9cc1984d4153b4fa46e5174d14bdca951a464d54dedb27912cb27b74bb65ee3a11854dca6542749a7222e589f4ea53bb8c07a84c3271bcb371d4005d04bc825868652df8defcaed9f9015e4c1d953af10992fc73951064c5f37e02baf73531b0eb5c1e2a7e6f379eb60ed2609e601abf163214e328a9f75ef17b308bc6263dd2884a5a8c607be1266bfacbc26114d75a610805b1be34b0887182859a54f6fa4b06c4275959e6b6b5a4385be6104b61fff2169226e389a18e1ad8ff1ed4eb1c99f35f4c198fe777bfe475759b4bb82f54c47218c5bdf61d506dae4b84fa4ee0f64f2c7ada1f39617acafe3649e960d1804228fde6267a6708363bc10e97fbdfcdffd883f8a231ec15263608ca462440a882a488266d35a4f878f55e07b6ca0f994a0a1f16b743bc9e5f473de80586fc18f09f0a13deb00c73a23e818b3e9241878dfac1f814bfe3b934fd0ae8be49caf16320fc729bc7d8c584d192a884eeb2ef3ad079cfb8626fcf1024758158951c6dcd607ecd7a15658e2154610085f1e5cdf61704c120b72d9c6db247fd04581264f6d14109581ba6994dbb46437de09164bec86b384ef16648649cd650714f6e7c6151783af7c4db4246683116e435a6e3c4031f21c7aa66984fb64b8d9af6e32b2e4cef4ec8ed9568df38c067076e3f4536bd37b4c66f11a426e9d76cfe29ccfab367ffcef2264b0e0fd3513b862db235304924f2cd8d07b2690771c778cf21d3b6d4e74541d390040a8582434c55a6d8e6af99c67096455b5b17cf5e902cd9928f96e7d14d4221a2617297858249b9b7235b28847f7c843d69263eeac9c6612f", - "tests": [ - { - "tcId": 80, - "comment": "rej_bounded_poly (sample_uniform_eta) requires 277 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "447024ffde9346a213b39475099459ebb1de800e2879512a7f6747cdcaefe85abb973bf9e25a460bd9ee2ad1bd70a820d8f172e54eb46c78e95f860001323f6617d9408d2e1d25ba6826f19ff9c010fdbebb0c002c2038a178a78f652f567ecb5170f26601eae1bbd555aa8fdda21ba1dcb9e351620350e347397b96f2d29645f10b3d8945d636e58308d85205739acd6b94d671a3cd14678ad953218a6b5cb7b3222c2db794e0cc468ef45358505ace711352899851c324c12767e5a50e5288af2eb3c9402114e06e0ff0051e9aa0ca2c72e6fb479c074c04b2123e6d6f9e62d4374e0fb2c3b6662332c391f630dfe44c4fdb7dac95ca3aff5a427f3d7814bef76f897bf0a7cfd2bd36d9d49f87b870a06bc9dacaab0b129b6158dea464fea551ba4c5431237a189860fe228ec8840b5eb358a68f1d9ae9dcf90dcad2a8603bb7fabb4e387ba963b08e1dd41e02a10842b579bec2a2d431fb9595b4331f46c9b0db975832272ead202dba9be105039328936c939985d1137e2d90d55d4e6787ae2837ab48f0562da0e0e58c8075b4eb5dc9dfc97635bac8866cc5f13f984869a550a100f13f3f56a38b8a350fa4fd06207c1d32eb667fc6811c33db6cc428f620dde08c42dc2efe736aefbe59c167da7793f2bfbc6cd3aaed52d3757e8d7e44c63ae8f0852d73b5ba5569214c9c1980d3852a0b88d0248175f53e9d11ffe19a1ff5ff7e44f8a5c1074731c69198de1be50b7155b49b9875bbb7473983ceb447b2b50ba230f69155d7ac4e46a4e80762c39a97fd023d4ed38f7c425902b7f747a11d7797e2f4cab63d27ac2bcacb17d08ced68b7cc5d91c69bb8f80f17d9875119a741bec5757f66042ecd2e00847c0390170ac2bdadc769cb501ec8aa38c859441d98e5bb9fccc43eba593d928209245e6de8f336cc0e2680c6a73e5df0f554301cf852fa3dd3e7d5f720320d6b079cf2211feb3b2956a0de3f59bce94148dc91e9b0288445763117cd180f7ad089f223eecbcfb06746aa2796dab2e620459919cb4faeb7d4c0d85779f776593d6fb0877041d43ee10435cba6c7baa9931e4c4dc56898a36983312cf85a1a999bcc02cb26d091b3c5a23fd4061a09b44659f6d68b87b68d3e6c18876f9f8f8edb42210ffce4e4c6a4a01584ee1b43709473130166ce9d9890eabebea8c81d532c34a166dc9dc30f1d4c0546de34990cca8a5dc6269853d69f366056f23fbaf72be1fd469fee612fa9a75feb97c079c5c04fce08f89e8087249a77e3b0d73728e95749f7497313631ad95620f3eb3c4ccbf4cc64e6113c4044541e843832a32ad7e699a75947f8ab7e48cc65a060d62972b86df8a2fb0b4bb966193545c86f201c5be342dfb361dcf2bbd9f3a22a6ec498da9d9e14770f9b7f642314bc6f66954bba2b0c621be2b20140eb6a0f536c6178fbf631ae39cf1c66d01c35763141b689e6851d578b31083f2153ae37101bda7d5a1a428582fcc19b310fdbac1cecbbc3ecaec93d73083f9f9c0f972ce0e65cdf5db90c623405863a18a497fe23bb57ad71f64ba9fbde1e462ac28e0d7597742b2eec39741d11c406ae56248c3644f3ac44fea88050fb4d0af09b65ce58cf276b37731d21840f34a9bfcdbb5322d905d88476f89aaac0c3f6ecc7957747a8343dfd8981dcf34057746dcf440aa098e5d41b5c61ce15a72380b7c8a39c982c052cc1766364fe7eb94a49441014deb484afec1692738d50762aa0ebddeafceb7b9f6cb2d384f049a104a584dc274040f4ea030345f7f887758d10864d8c4b27abddd214be79c79b69084d71897ffbdaa0dbf5cec90f22ec07d4ac7ba12ae6ddb130ea34f774c2736267cb13178abdedddad0e0f889b920b3c4b3008ce7b18d4ff36e196b1e7d8dd043b58495e6b7dbfe22d03ec72dcbb250ebde631f43c556ab8b8465b3d76ea1cf571e6726d39866fca46a0b515f0d8479a028517f9021d757ef84fd8a8464311c7462262c82503dcbea392f88f19dafece39ca11b11ee3649840dea7054fb02770a7a46c15c162a05a6a2b5ea904f2ecb78be936e0cc54327564d6097510977807a48e1b446b5076176cd8be717380f4f02f30b5f2d2c0596f45d3c064ca4763e649c9396319eb09d37d3627d3ec6ea58df23cebcec0c9bb68861d0e2fb56e075f2aee9bb1aea052ab2c05ae746f80bab8d953f40cf18afce5f331b334b7531e472d942bc07e02c67135944efb5aa7e39e4344d365d719776494ec43cf3f64d208db184bc4f1239eca1b744055c12d4519905c66017a7a8f6d47b3f0a725222bdfde1c1d605d04cf93ef3733a7b9a5a54a0de03c66866bbfd24329a565c0092856e637a832275f6ce6113656a71c1f1ef90058afe1a376aa00be83e050169b7f9e94451dd6f493fe5caf02d6e5cf1d41c5e7539d2d70ca2ac35b966ff9f66b07401f25b259000d14f9e0aedd734b74fdda9b187bfd99a7c1d241e40f87027567316a3cbc08bb70ade50e75e349e7f3d023a021c46e84b2d44dcd04e6a9c2a5ae4ff79abc2805a5f71684b8bb661421008f45d9dbb86387beb93b07583d0cd4f4946e5c16d4b62154abb7dde8b771e22798be9c39103b5319442ae8f49d5e42ca2f90026ae62848811fc38f2c930f0b266b445c7828e3d8fe4cff57b79d168e51beeaf15c693518204f5931648702f81afb1841ea2479c8acb2f42236fdbb0a99cfe83cd3cc58ad94908d61ce8b953e433599e9a086d5655508c79dc26662950697348790bd0905d4bf616ce4f411c2f76e4f91c6159c6bb317d90356c23dcd001a43ec94bd8d808b07ddf94b93b3191cd3fcd8529197f7aec255c2a25bde0968cf689263e0a5cb19be444f36ca797376b013b244f510191bdc007ac33f3f8e73bad30638679bdfe3adaeef93ee24df4fba7c405b5be5ec54cb375a5b9eb19473e981fd08b6f7408fd00e6cf2971f63d4d4d4b9ed066318efd0523250e0f70562c1f2f5c7c7317f999c74680b811baba2d84153f7ca6d1c7d0deb5ed31da60f477754725725b860a64448cfb8dd8c107613ce6671b956e6fd769ed556f8bf8310dc2f167f621de8421dc13edc84cb9c05eaaad7d9d51a5d7b194f8c3c7082e9d53c5c7a88e1c072c468a835445505c990379d34a2231407a1035c81a0a546ee27b1b3e7908d4921bc70721911a2c0f5ac25ea8a81b2509d40f2c727a9f1d7f91a4378fbc21145320f1b9ecbe54283e1237a5b90b44c9f49edbbc9f8ec73af7e6e7ad0604b3fd84191a24b3efb2d07db8bdf05b742a65e7405ef50e47fcc92d4029f7f7be4c5e7f1b3f85d1b9a5cf8c14228318ecbc648fa7ae37b3bd3d3c33bed9bed46bcd47ce89650dae8cc2c5e2965d59006b24beba14e70b1174cc4f828f11188bf0c21d552f1e5fbb022e84549b05b3f1c2936014c1c3163269abab98508a5c3a4b0d282c6b91aafd64866d01bd8715473fedcaa36ca1f1c6bdb6caf82753d49a4395b3423fd33b96313ecf41d728a5a57fdb8d01c3be7fd831149a0e0dbcd323ae4af4d062079e0c4039a7d9cd25fe20f033e5ecfa0d34e6920bbc1e88398aede6a28439e700e8844d79967451a3771d4b26eb5d012a49a5f817651c1d752163ac517541ca39025aa428f38dbf3cec4d648cfd3922bb2cd2eb8e18ffa2adfdee5b9314a82800447ad55873b14d820192cb62bfde5699b680f2b0ff07e2fe9862128c17a8d2827d5aa73023c573cfe37d372b39c13b414b1435c7a4951cfab1d8c74115711bce198053ae6a3d24ad64600e9c1f50915babdb52dfee9264142b108312222d198810898bab5e09dd09a9a27b62b6e7d7917708e7829903fa5ea835de5725a83d034aaf7321f48afdcba299086d4b20075e0537bf6cedc0b50a1e2babee1090e22e234279d658a75142ccac00c6bacc16704f1654382681498908bd55c4919e841323f4ac8888f1514f4dc9be789c604458de0ced5143c5b1c5d3a64246a68b5c3620a5869eed93bfa07ecc2711bfed1d8d3e927aa16edeff32df5ec23a53e4cd0aeb9b83cd9e67ca15be9333960147c96bb33e7ba5c9816a34b93347273c49d14423566556caae62a2e5d138498ab7d45f5681df334e885933ed2f45c1f726b4f0e231526147f9a892e78a9442aebab81060032dded67709cb278c054d5339d29025abd25b68f32b5742c9e4e313c40293a32f897e96a9422ef349d13a70f5993221fd921d85d2e55c0517cc0d241119a9b248af27cfd6eb37f6d9551bcc7d7db3f53824dbe2acd6f1c261cbfbb346ebc42a17060a01c6cb89c95f048bbc62cdcfcbc33177f5020583552c4093b278179ac176a20451d4968ef4582854ad21f2ef78c79cd5ada9cf2fa29cbd63dd4259901f5327ed3cb92f792e12965352a2a5190387e7d47eaec012daa03b3599ff4713ec6c90d84fae59f45c99825c4b9d54e1b714ae0d13fa452da84b95c7ceaeec30e11ebf55dfe3fde91afcf54673390f35b5f4d57288750bc6e203fbd939b7d3aeb04af68abc9f454132920a95c45bd7fcb35ac27d1db2ba58d1a4dc425ed4a5d315cf63321d9e7a96757b29bb5a448b79b2a85883335458098a8b41f3bb7c42930343a636e8d9dd148bdc22d6283afeeff0817287e84c50000000000000000000000000000000000000000070b14171d23", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "01c8783994aeca990b8c00ec3a55a898e3eb84efdba12db8f3acecf8ad5ab9e0aa86001124ea2b7ef3d568073ca547a5cf5b551acba08ab5e2d9a184106de7ed3ebc9a6b537c42bf577587df3eb7cc755be7c9cab128cbbd9abfa664069c4429ae879de03a15d2d7ec1e00b13961a76824115806c6406f9c4596b74e24529d0dbc66b368489523adcc643c76fee32242a8ea269bfd7ec7b8cc104a870cedfc83daea902b43f6073fa53541b3bea8f41f5b6eb60f53ab2fc2d4f3538a23c076eaed8f57aa86029a186c1ba082fc402708200ea69140b57b94085e9f6e40a9c2d712e9bf4be24b2ee1e61532531d5b9506b463056f63be7a4547fd95ba897950d42fba84e590ff51644ad54ed9d3e20aeab446183b3d728caa6dd3e13c0ff26b11b2396f4eed6bd2b1ba1fce40f9496688c127f2653e83de66db465815f79d4a84d6ddc8d0e9ba6235a7bf4a1eef348b654aa2c77038dce7c67e9fdcfbe6494be1540acac2a0a10d7d9cbade59533c893e2221d061b014620fdff18e34551c706299d0a6aab620dd5ec42d2ab09b42bf026ffdc49d7a624e7cba6180e22cfdad5ca927e9ac5277dc2d341142b793b46f44ff8b24c934b582dd35e63d072e014be1c5c3bf94f44b1e96cdd2489230d7b0b01be94d74964f85a14b2c008873b2f2c142cadd3ca6f7253842f9398f0b0f3b8611b3957aa4e5d8097278c30772d327b937db17937dd79759c2834666c185fbfe2fac4412bd3b3c6f95e3c1ae476389a1b6a350f3121ac642a66363b3630ce5c0d6804f54348b05e9a501bff54ff27fdbad36bed90ff689123dd1f90163f483f3ffbcd7380dc368d631b98a43d0153b4e1ef895cbcaa375b81705d2d8e8152e1daefb0448581b7e458edf90fd4dc58274f2393771928de20916c0ee00628bf51b6b1485cc75433b7756a07364746a4c2a38e21dca103f2784ffd5328ae1575f7359447b27c4f380f74d934a7c9a5e2dd0b382d84ad5e60b4d26e0e35c6827aa3663ff89550e99731857513e455e1eba734c0feeaa50aaa543bcb935fcb23f327927d86df7ae19cb179b4cc60f5a7e62c16eea7bc92a383cfdb4c80b837de045475cd837d9e3d1c0921c446bdb364b18ab4df186cc966eb551632f96e04e31835a8e7a08f14674b61bf3b45167a4f3eff00b2b754777ec52b55487fba51083734b3ee1124a179503225a6855dc213d74c12a644b472d434af24dded4789e3958d0c9e9043f8eaed5dc0f30a9a7afaf62587f800f828816f411f220df65e436572aabe887ace1328cd6146fb789ae6cbd050cc4f5611b0b533b55267d4cb3a3f79ebc13b4e97a6279eefce101e5acd0672665865ee211e99365f9363ec9e871e029a9a78512501cc5613388cf51109e7f9293609afc883dd9cd570d3facf8b57c7131eacd6cdaa130a9eb2559687eeaafcd5cbaa752b3b794377602e7e2dd7e450361596715ebd12e1608ece781f08a7917b15801cb3c5cf5b345c4b816988819e360badf36e5d52d8cd66a43a980b952d490c48501817434696b9ca061b27db5952ba249fa618017b7606e8a24b531232071e513ff20c2e05fca6c0c3e42f410c8098e02347dbb6fe2061e65359a187df76be1400837c0793aa0f9c0d1df64275a9df16a50b7d519f8b51ddb93a2ef0d82a616f7b4e69a6fd58ba72df593b3634764ffa7bd935032f00d49383c410d69b087d17070521d4ff49aa57cc46fa23c5edd21ad1425a1356740ca98821c065266dee6b41187b193316b1df0dfc0aa8ebb3e276c5cc357ec3420aa61ad588b01226ed7c653578dd42ae2be5b4cd36aa28bfc9afb1e51cf874605068ffffbabe15767fdc673b975eff3c92461b1b4aaaf3ccad8b3fc9e387ab904a8e572241923d27780bdaf3ce6cf8437ee66be074d512b3626970893d3df678653a220cd059bfdeffad46b375ce5f908c398542f15b0b63dfdb0f53934d7a8fb10a6bbd93962e1151c9736f03fd336d361605d688127f021cd9afe3f8da90af9b1e8c9e7879a7c30aac69294141099d1d503c2a5133f8b0bab47407693d7cd86aefc34d94743fee73738e7cdbd144ef9792f90ccc75ade1a9352ee7dca62e0358779105547a636cdd73709804e21bcc56c81190b786da338e398138e2dc52484298859bc7638d661fdd06e460cc47e7a533d76befc2ddd3728f402a0b5c7082f6a1f60e96e454aa11f178a1739f6ea30b7f6cd7969617ac7a42240f299f985a59db2a1036079e97b626947588c4719ffe3263b02e31c2f0d43f5acee913bd730611dd4b6146d16db5baba98de460c21f9c5edfe5e93c47f9840551f55b9e08864f68fdea344e43f83d7d7274232591257948d11087d2828c7bc4f585c8064418608fb3a004233b2e5b097ac2b60481339ce0f14ef5cc7a21d23a6465f01507639ce13bf12ecb2636850784728a89ecd9b6b31222c9e0249246abd1820e5c734b7467db4d10fbcea65bec7f48fa058a5c1fb2dcc76fc480d2e5aed0aeeadb238487de0296efa2052083942c79d2b10308ca123724765c7f0d34cda9c0f724504dd0b765a6bc844b1a457662313d5758419384d12c6390b32bc708fa67ca46425fa2a8ad1e3980a55af646ba6eadf4a9959dd206e61183908e70af65b63ef8da29a9d98e1c9ab5214fa4785590134a1e4df5fedbc81179557e8b8eb9332c0a5716e04411aa2cff283c18c55f8e81c59119c05b87fc7e4ebdb2be4b07f0d7856f595a5a7e0848d7fd", - "tests": [ - { - "tcId": 81, - "comment": "expand_s requires 2649 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "a6d86189aa75e8618ba96982c40f35622405b0d0b2f6621b7d7eed57d03eae4c03f3b9ea48a6f4f8d272487b4da8ab4055dc26925aa8d5636537dacb2042028ebccc9613411756918f9b699242445b23c1169a8bb525e1d4277e90a9ce3f68075aa9bf3634bda8b7e6a763df2f614d8fd9ed73ad5936b08fc63cbc60f4625626fc5f5afe853829098a13f8267aa6a76a9abddc1f4da58023b6be547d1e37ee4a220bf109233bdd4402c04a5119314c2747481966d106c333434b03fd1c4c37d47e459785cb50e4a37c0293bc20428a51faa666452a3f60f88ead932b74a45feb3193bf10d323364cf807ec7193f038770e0936bbe1d96fc758cdbde7fa7fd5b8b58d2ed25064500132edf8c8a0238f0ea7b55da8cc089b4ec03cce9e78af2e710b503b5ffcb95e564caf089aacadba9653ad780b52b6f0af8d44cd8aaa5ef8713851e691392b9998e8083131a9139b6939a90a372cda707cdab2423e72ceb12e1138ffd125d4ce5c2c69b601ac6b97eb77b30b51b64cef96e75f267cec817dad9a96a05fe91301dd58586a37c74f914104f5a8cfddb386a93c237c35b5f616a7615d58ebbfa71c3551685368c04497a3946fef065fc39c37a656ae2b6689563fab0c321a7c2b92c60eae122345145694c65ef7aea65a2a4060997465c0bbff4a71d811cfbf93edb022e50c99fd92394380559e78a5db34b513c37566148aa40443e31d18e977bc35b1260343b8e32f6d4ada3e60d084fd6adf097a20ea75abc810d8adb436eb5e3bcaca06b1d0852e9301d7d961571529a777cca4429cfba1e8c325aaf6bf24f6c8b8123a77843f8080abd9bf441d717aebd483f1cf18e102b042cb2e58a0bec238cec8b5cdbe61fea4f9c6bfcfc0bc022ee5f50c7f5b36065703f2cec29a73795f0682940126b994ee873be25ae55d430b7a671a9835a7f6fedf4964a09bd1058a5151747e27430be0ccaadf8d2f4d3e6aee2e699cf06052f77d0f9c503215a6b2004ad69acdc8747ed63d5869d8cf3bc9911630f64cf233c932ac71a098a982012ec7e25dbfc042004d8f530b9d9e24853725e679b6b751cd7bf80b25e4734f41971938df86e2eb70dfa80a2aa3e31ce9393737c14afd5f7470790f380bb8410aba8152e51d070e71a84cfed8192bd9d3ab2ecfc627fafa891e93bdd5d0224f67d857ec37ad2d5b3ec6f9711081b3bfdae4d05c0b36c70f35b3df8b174ee7fe08c4929e9c5702ffa20081ba7eaa9dcd8187938c93efee081b8854ec3983f9aac3a1fede31da432086af172a6f78776a37a61dc1ffd8e5cf2f1dd3420d8a1dacce8f44a2faf76e892bbc4d3ad744f745a7b5ace2e1943bd70d8f366fd200b15431e20f73074aa1827d59dcd3714c36d10f4b5e0b22e2e1794983e53d21b94fecdc73dcdc048df6796b4b38aaa4414fdbaaa656bc63aaea5c11c3a7c11f8cad30f678547820487959b9eccd27e96b7ade1294875ca071956196da01a9802309e27252840649ab35a3b344b178aedb82c6e3741f1049904427a6d57c977c41c42622642ff393c7aa178918d21bc414d58c81ca8953aa680f2cc5fe7188038cf1f4a0b6fb257e1c414275b9a74caed761b83989934953a19baf98a9575c35e52441487f0b7d5645215159fcb3b7b6b193892886024c508771cbc4b3f120810c7d126b14922d6f386e25309bfb4c1494f6eb4c9572e40856150f00cee661e67e210d24a147ad19565bda14c8de45a5edc77a4865e2b90fcdfbb5003fd90d7a758cf408a96b05b6237b0728e41d5847ba118fd8d42c4843b3864e3bf07c0b7136414836ff9ae6564340d4ce226b1b608b53ffeded5c14e91aa39f869b602355f5754c9c30958cbf426d1df86a498276f130e5b0e3c1862c440ce6e41ed1d8acdcd0f305a66769590244d672d34aa4b72d023332f5788649550039975e467f196cb35a276b6fcc394043ea6924ed262a3572bd354b3685d98e87ce4a5038f3961e89764359c5a507df56c18b030eda095ef6b3568ef010f57949d3633f397a7a04c319090bebec19f521325f0d8b7353a210d462e5a3e70d768c1e8037f57b51b1bf667018e354a14b6cba7d41a23d85d1f2e0473302dd840a085fbb0ad85b19d3e569346a9407329e24817e8a374156f87d2b6b5319f5861addcabd1356e712fe3757ed9230169e51c0f3234118d20f477314514e5aeec9fbeb0ddb58404df022acba911ccc5e727475a36dc9709875303807add451004afbdb4ba7e3ce36bea2ab5c10dc71fb0daebd762a93067a465297c83d5f49b12eb2c1884d430b24c3866c900b5ef882b0b819eae3a5eaf8290f86afadcb24e100fca7538672b9a7c2ff654789319070a363fb6de40fd79e7d2d35afb5adabce11df381c70c0cfb9369af2caf58871e2c48020ea23e7d39195c1d7792651077d8daf2627c0576facf26b7819f92d01cd2375432740cc3eccf93e67803b86802f176b8dbccaadd98327ff492e5a6ecf2234ccd6fab3cbc279b5ceef49cb4d93008dbd9429bcdcb1110db7fcc828ee02f66b7da8cc80d2d6c5f4fe98d8e64930c7c4d5dc20715ed88a6aced33e9b275a8b8289566d67b4f9d0364931f0462a253efd5c1e6db9e7f79a999b5f60819110898d07cf59e6c0cb39cc252705ccbd381c7260a23804060af41d1a0c57d4e684bbca270c608b435082ee5137701f433f3e99ccb3aae30a4451ca36f0a7319160d6abe4974435845ef133e3711ce15b46e5cac0b37cc62a4ded418e648deaf27019d6ff0b821bf8c0eb0d84b531ee8d98f14f4b7dccf6eb550a525746c8eef4f1d234318dbbd2969af3012d44768dd40d2421756e076bc3fc70783de3732de15bd68464f20a7980a58eaf6784fbfcdb8306e10fcdee3aea4e9f9dfc08549b9915b0df736c337e0f918913756e97e7029bd00f5f6d946de70235cf5ac260bb39eec3f71ae8dc19c7bf54fe03c6f894cbab5867bfdcf2568ab8defa4a15bca7421901f907b726970192ac2294b5a90bbd0fcfc2185e819fb0917c4e83dc6088377dab0a080e036c401a3de501764b718990c8514af6994024c9328d0068802e63866dbf911ef1fcc05a4b831df906c2efac9bb79df60a34def5bfdc6eee7425f1bbb21619648c8f4b01d8f047debe8b1b08b1ac090bf83d4363909886b40b4f3b0f1ecd486bbf7339a4a04466cc01ef7c5fe2ed61ad912b3f447b300bcab8849917c05f8c3b8be383d7f46909b2fa0ec95dc1f77e293cea49806a581719e983e90e9fdd8097cdb92788bece98aebd951d666c22e6fe06444048d674e7f8258b22b38695843b044213e0b78b22cfce0dfae13954900338c66e216103255e49691f3f36dab6aacc9d83ea5f93cb544509e0d75c92bc7637374aeb8a0211ff989e493d893feabac80644ea092301f07ca1a1febcf0276d00ea8627aa19ac3d1b5a374abab473b13b79c202dd555fde622fdee1ad6856988c59d000b4e96e1782f42ddee2f949ba17285a7ca4bc78654ad66068d7a2f4bda254748b2685966a9da2e8ea39bf7cd8b05651c6ffd7b61cb29bccc28b7bc072a6a2e76b1005ff5adcbef1394dd4ebe4a9e47dacdaad90943aeff3336180437964085e28ff94837871179745607d11d71f4f2a04441e981b7b4d3c9f85475c2e1e89eaf8b8b2ca3ea3bcc5aade6cb406b73290fecf015d36c5e244d3bfab75c7dfab47b751917158fe333321b495478eeab4ce2cd91173ce2bae318fc3d6906f10aa86c0abd975ba889e958e9fb4fc6acc846bf7196f4a42be5dd51c4d7b5f80303b0b64e35908d7cee503749bdd67d3ff633169dd4bcf39617de8067855a4e0acb680e2879795960931d3102011ae6242423abce1ee4012f7efbe556c68371c75b857c5635297f3ba7b7e5d6f030f13f9177303501ec67315198e7bda9f3434bccc060dd433f1dc4246f491ff255752d8cb103e278d5f35546502cfe85321a6fed500749fbb51316175f062080a20d3f52da159b448df61599f5754ca046dae3a14e9e03525acd9a1fe964c8caa9feb3ada82320d2fd4bae1525830c0a3eb91cb454f9dfa43c6534dfaf6a7e1d2b19d527d4f403863518f63246889614972e0bbfb126ea0b509f0c78278ca1911797fd5da6c00c8b6b212a511ea9bfe7c45fb742a109fa40f375490c0b5e98aedcec7076e1ecfa567ec3575cbc0892460c52e94d9121c4a9219049b7325f300f04182373a0f476f91a18b4ded3ace3d001900f9316d92be485b5dbefb54fc2b6ecc79609c03b149bcf2558ff915f49bbc691b45c3983fbe61b09cbe7f17bd4365e7461ff2388720fbd74ae451f61f73f8c8b51afe87e8684508f7d64ba03f2abaff47a30ee51f32e25b9d07371f578df432fdd95504d64be891762adaef094318e64a5dd86eb81decae2c30c8fdf3ddfced1a6f1a3671b6687765f9fd93cf66c52b8986c5ac3f78a8048d969fe78d057f8779a450c4c7cf554ca935c9f7ad781dc3f50ee6ab1afc087f35e02889a8cc70a333edd334688c70e85e5e33d7509ac4cd6e854791cbdfade909fedc5614190cff9b7b4f62951fb40fda1cf62ae77d00cfd450db333f4c669eea1877afb5babce2f70733396777b2cfd1e10304272a373e67698c40475d6a8dcdec141f999eb0e3e6eb0000000000000000060e1720272f", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "b41031e429023d8b0bde433401da448cee6c25c6ce0d570f91fea2e8e0003b8d8b3efecb56b34a3ade96b17d8b98ed28c6563f381cea1da2898be8a0dd4a3c7f187ee288d37f0fbaf512d127001c713d64dc036b1791e239d9f8494629b6276d0ac1e56ee7644e0bf860f098728ca4f225b500e6975a548c52d422d3d1e4f1939268060ddf304515490e90660f848d839e219866252b107664c3481aafc8afc83ae2d43f448aa51d5765ecbc910f241bdb815a4e11bb84309c947eafd69fd80b2f9cc66afa06ef67a9fbbb1fb4658e3f02babca2d96a4d93582442db9a245e1d979404a4963ee0f70ac7cadab852cfbdcc58ab0617fea49dce099a430f835f70240396aa39eabac3ec22e3ed79d724a77d37e40b8161ad8fc85c930e76d714c12b1e636a00897ea7a76f18a4df312cf7a0861bee298d6412ac5a694ac34473151728cba9d3026879332a23d2562e8eebd9324e062444696f78e70e876a8c197b95c82bf11a8588a831d684d8602cca58c4d8030fa904cd71ac066486afe9d3635f41611247715d29854ba1181c3ad312a7a28bfb01796bcd016c2f75d73fba343c8617b534175e06e4d9d2186a5e9d4348fd942f885fb569956a4f0e59ba57bb02f7cf56d67c0bd0db375bc95e58a23389cd5293694ed4d5d3fb3faefa4dc4a2e59df6db2fcb8535c37e1b4cae7e8cd0fa0d02a1b7875fa324da4c9e9f5dd25b56b313373dc7c23f1efb257a08d829c3bd1c80519756707869b2bc6fbad96beee610238142f8c73ca7667106c31d88f223b47a459baf382e45d347973c6279e62a77f8df2b489e1432684b0230ece5f2ba6c7e2ab70cf620436632f3a516e2f269995fdd4a36345a201d7ba22887d7c24c5c9cb8184c516ee4d97dfb4437a5ae8ef8062464d8badd958ad779877b4b1642505e3406b2cdbcca77c33d10905501d556c6561f4b64d5ac2ae015d32c650f427593e25b34dc334ce4de1a641c5544186ce6e852e9c9bbac76dca582de782e1c53b1dcc446fdc8fc1c141903ceecb37880fd6d5bb08a481a2315f5d39956529139d5250aaada5122d39dc5bb6d0f96e17f01d9e992ef9b220f08427ee83cf32c69058a5f24a0aa320d18923ed91661f5f74600f332e121fa51b628c086233cd9953a1428d4d8f41531a7233327f05ef347722294c31362995ecbe2caa069b869e9f232867fed5ec9ab09bd474c9ba1fd1362ae742f8f9984ae50eff7086d32e8407a8aba62df7817d694054d8d063bb6ad34b85d2e9c87d90f4338f5b92886b4a0ebf90954bcd4a7f561af87c966aabe3cbc955891c405355b77d8ab9b9ea0b149ed17266743e138ef94cb1cc823bd714ed75cad9498cf2375cb869af424abc95b05234fe24a832ab6829799312b9370d51b293e4c3e3bede66eb763672b51e0d567dcf9d05c5a3db7ea6f04f309a10f148292c33bffb8910bb67ef3324c085517b6d364116dab5f957ffe1866364a0b73a75ca5f82af7fcee26f7349d7c11a3424171b58948778e2dc03af2ee4b5194c777e337fc5a4b650558a2fd980fde30becb2dbeaebdd845b9e7fe98213889def8c4ba33c3a98acd2e0f9c6da0d9df4d53e06e597c1fb5cecd29bc0fd34446d48145a32633c74193333711d54e27db38fb6ae6cf0644822be6f6ba0dc7a41f7691dd8e3a7fe3c92ee4a7b682b0ae11c137fa1ac96d466cf491afaae57998e16a739de679d1d27f795f3852f402e8742ccd6d77d104598df9e9772ff775cc422c2508708e971481235e6b32d0308bb203e46f6c883b1736e17311855b61bdc7f776ae37bea27ce9dfd8b421531d556bbe953a703c4ca0c998aea7541be8b49c158b414415072bde726de24460a3b6da8bf23f9491e41b498ecb1ec07ffe587ae9a16d852eee18a6259d8f69ab7aa5875850d469f471173253eb72a81d546f31dea76544171cb4d0c6eb636b6acb2d1c9036339519fbabe0dd036b0fa69d0c207cfb59c3c3ad3ffdb9a8d6d353796515e5b606b4d07a8aeded5767c6be8c6035cba13cd948a0466cae07c8cac13898461b6eebda444b7b3a64ae1185e27fcc59ded90d8c0b9188b9538783ee0b0d6f90bcc753a12f33ad1e96b24585994f7b7291b4a2f1b240553d4c9e8d8e6fc4c354d85f2928b3551c20c97ba23a053f04fc11c72a4db576e76a7be027552b7903e9568608811258396d3f286dc307c4c05a546655ea08e8200e4d6002374043559b768021aa6e036144df0ea32e1f3f2a158fd2655d6afce1b3721353e5977d59e61718c95e026e3d9069b97e146340247fd7dd7c71cc6d83d2668fc36740098859ba5941c548541c776f5cc38ac3840292e4d17879ced0f72d892c297d15afa4d1da9edc7e58b1c44302b504cc8b926442c03f900cf683a7286b844bfb35cca31ebfa2721082cbfeecc681888afd938a2314cc4f667d7d5a7dc5df04b6071f108f97550d5afc29b304191aa5077183a970f099cd6c59120ae1f95a9cce12a59bedde1e499a20cf42d69e86430d18474621d0e4e4edb1b71d991cde47e6509ff8d1bd2f86440374213a28487afa099b69cb78f357e9a64dfab99d5e7ec01499d077095edc842fb32e185b83bf1bc30f9b47c48c835a729d1fba5ac37fa941fba7d05667a787a5cecea0b8b47986e897060b7a8b93aa5920f1e7e14c5085d9d2215dd6b9c2cba0ea4f999fa35d425bebc3a150c7296b208ee0353f7d23e14f09b2e5c05128e08c97f56d79dd1c0dba1fa32f", - "tests": [ - { - "tcId": 82, - "comment": "power_2_round returns a remainder of 4096", - "msg": "48656c6c6f20776f726c64", - "sig": "b35a9d26d3cc6ae8bb05acf2044555aeac041165b78f65f13831ec482972193f4ce7eaff57bc166a11206ac59e51f798b7a0b3776e447ce2941b99a4e0f6238a8a5f3487813e1cd00260127a67f5fd09222668f3edd5db27f9f9223417f82dfdedf9ab5ea6ecbb325f2bd4669d59a2bb8634f2b658d2d3362a79454372e2f31f81e6de020436f9bc21db4e2b368a448aa15204e170ceebf7b767290ae3634b094e569375efe46b71c0ceafc9af5eab65325403e9f7573323ecaafe5f0a7b34f3de08f124da2e2075b2295d2390b41c737b48767782a83c09d46d7ef1cfa8eecf154d35cc8b68fdd4cdc10c04e0470953221962cb98ec479d80461d9608f6f489cbbd6266b05266a52d99146d76060155a093eac3c3580aea48f183bc95aa2b77a00bf5f110ece9fda38a344a20eab6be2830006fcdc5cc5ff247c357a639f665562a527a99fd1c0e69b37d5ccc50c65c27dc057d6c7be4f970b01057c612101dfe9fe6bf23b621192c5e94a8b411dfc3bccfbd11a94ae05869f711f1fd8f6ef9b7f9b1a9e4173b56c99b05bb379865ad9e414fa44e6ba4f67ab4d93fb045ca0316ddb9fd92d1ee08c3fd8e490c7e533fd1f761355c72a37d9b7d4814efcacc66c8af043560287b54004ab30b91c03d8a510cfd5238cf3ef301d8efb042d331e3c2ea48876b9dc9b05f2e941975d247defa4f8cf2c7bed438ae680fe52ab144e7bc9d0926eead50fedcd7aac60fc342cf566671e84b02285686a0e9c49e5e05807a6b96df521c38905ba9079e9aa6673a1ec2208f8b2dbf03dab944e909b58ff791facae78e429a60dca239df3e00d48fe4848033d35b5847fb9a78b3364c9b37b7e0a9f3c497e811187f26ccb57db5fd669dd4b5bf127b5f01e6a9285b607823a82062a096e0b8911f7b0543aa6fa36b0c2a5f29fce780cec024560938c61915873beb6bd642d67d609bb43f9d8b8a72859fdb13f42f4f8ab60bd23725ddca6f586501e929d9b889dbeee8955be8d3251d41c46db3ddb75b880210f447f40c6dc5bbc52d22d2c4408d68a0d8a5adc2a2c9d7348569e858c9fa5254a03f9f1e973c66752c6fb0f09e32e8a587a56107ec4801d7c1fbe2b9de6db7a46aac7291d4081a53c2c6e9b1b0afb4d5204961553f23dad621bec8078edd3031bed2651f26eba978c2d9e230083d61f054548090b8fd5f9a31af5ef2fc2f5b7e21345169e869cb8d2707d1f7dea43f1770f153d50e03f838c41ea4eaf4679d52f23c6d41727c9922bd611b185bef46a220a0a76c7ee1d45cffe889af4331b9f6b9665830ffd9b3fa335e4d0d66bb9f1d835d7c123abb334daee683116de8e4342d11ec42a834be306f1b39ce24d9cf838f7fc8ebe939abdae09f8ee7c10adc56d26fb6a928242537d372890143605bedf8c601b031fde9cec47bef17e4e54a5d90e470cf4e826fd69193e94a21e32979c368fe9ab7dc1e582d02759f7f6b8386f4b005f3c4e956ab528b8436714a132c667ec0f21fa9993d37624d8bec1d9d759f28601afd8c7467247c8bff3b35d0fbac82604ef25e4b88ea05f700222baf0b633623467e0b191d88c1bc550a1dbef2813df92556f48c99cdd22557003c3c8d39cfb91316a4b13a078afd5d52c5a8e07009a88aa93ce463318d89a1cff5ada0d1609cf0df966b0ca14beebbecd9079c09467c1139ff8ba25adeb114dc51f662d76105cebf40ec1ff82879c8e3a653343add75ec4d75ddc6f6b76ef85092085b8d121ea81d875b362d95c4e28042df3958f16c7218215e9039c1cf485ff3154e46d3f9825a8e1f74e2134dddd56a81d8c1a21121e2dbaa322926581cb75592b99c9f90568f9b6e1e36f0fdb3a9e5dba272403375e42f3a32342354a798b26e8f295a9f377e022be8485513bfe6cc05f896cb62292acf714dd81d1e87ad89b38bab5532e337b2f326fa6cd508ff2760bc2501d729a66d1ddfbf9d622757c21b2a5308143f198eb02035adf90d44aebcd12fb161515025198a26433c7adf75f6077cb8a536826e18e4b80964e97c6354455306f3c5b6a8603c7bd2302c20faa46cba18bcd57437f474939643d7c25422ad36e56c3a80cf78deb62d9ef3b2de60ddda3a6c080a39c24dcfe88ed6a5c974a5dfef3d4b524d425bafc65dfcf4d045a1d21ddf393c73c2806ed7200a86ab718655f8951a1516ee527cd407baa36e27c72e97503a3280104d92f8248f1cb0c6c0d91b262fa39b8056796f954150d1a0911cd6c7bda3870ef566ded8d656f2ade63f13c62aed5087bdc1469eeb64418ce7af5fc50b721575e99df25432804306a89fd33c0406be8beafadc28f533e12d05bc3ffded1dd59cdfaaa54bc8dbf75b05f72b3dd555172666faa87602411ef6d97ff3254706b876844ebb3948f13e62380df05f67bd13eee4b8a2d7fcc53263072273eab92f8b7bfa64371b58a412bf5dd806c2b8054e8f6efbceee0700e20f6e4e61a6fd6dfdd170fa37e6559362e7b56c9ab7e27cfea2bbbf19c1815e1c863fa24c50ed465aa12583b345ee4007e9677f5f582c9f9377e5b0b12f34ec4e8f4199bb7a683142f07daa27951466f9d608389c17c5c50cd99834e5e975304e2ea1f6b6aca94a433294831a8c5e14dbe46017932035041cee0fba54f87421fbd14b05454543cb2e95046080da6ddfb81aedc37e51d0b1c3b6d036f8d97f8ad4e7752324c8bea832cad6f8afc499b35164b71f497d86d54c5e0cfc67cb31e01a6de5cc43b42927b20ee57b1267141eecf85bcc94c5469f68176f8313a706b2b1ace776bdb69c2fad7fa383dda1895c36836da08676a1a2ed697843f135c385831795ee32a5750fcf08013fbffba54edbd4ed3fafb6f5552a389a56f41f68d1a721b7b344f9e74028217c39c3c2aa1fd9b44b90173de0f986a3e2fae6e1cdd3458446518b2551a3d3ff4294dc2c217bfb8b281b42acca144fdf8c1ba08acc10077c06dd8cbd5d4ae2336cb02cc400a1f49ec581d1e2c62e1cd21be275be4257105836aa99631041b999a16d6d57c1bda6399aa50adf0d4fb8e1229d8531aadc834daf90408fa2120ccd2d39df7f93ea12af0873df00e201b4bd6851ccd931a23e6589f4f583772ed426ee324105d72a05e308401cdb99b283c93cc518ed7c98f230d3605e987b79f8b20d28f99c46850c025d26830dbfee8230234b3efac3a3ebcd322e84c604782830397697bd1308d07d24dff64f7e453dd0eee7161f7e376c7f5e108e04f22dcafa47278be38a4754bd7c9b657fd9aa77a76cf9889a2e6f0ddcec106db418d7329686bba394ee09c23629009bfb10b360f649e962cff1b0dec8d47016cd15a068a5c9d8a721096a61e91b00bc28816f96d4fb7229d77c4a9b3e23ee56f12cc973bb0ef158c0bef405bc6483797aa1d4eb1cc7b2e1e34365b99d3b970b8dcdd7655d143fe6f4e191b2cda90a1e6158f55553af987edc08a78355557c3c36a2fb530c5badc5fa786e6a4feb041caef1fc0e18283e00724362305ff84ac5478b4db29859b980f680b1ee2486d07ce2d2b50264f693351d2c7e03de1922bfcee5dd7103c9b5c3f5426141f293bbdf920431e639dc79e63343d48480354204e920bf276dffd3b2692ed4a9654c294e1c0c3a0eeee84549f227250a4bfef594ea0c3a68bc2c6619f85d0c96b01dd05a9c076a7a2cfb6d0e3dc616147d3e7eb7006f2026040ca208351cc2f3fe3a7e72d5f2ae2c18ad5c80e1d87d439a1afb4672729ae4d04ad517e5a5dd903fc1cb5ed3385a11762b5a4e5d9d7fe00135e6857df3bb623cc5963f0573d858a0e62d31d5ecd54ca5eb4f1344ff1ba7bc2544e7140c5a2b9c3b604c88f0253e44b31f2543ef0e682c5a50bd2933f8bc22debb3802625fd8963d373321a0088cb910f51762e496f50d822b9d445780ad78f6c8143dad25cdf555f6fa49eae6841fe8e721437c7f541ffff6596b7b52770f44cbe33e1ad00857a8d36c0ee20de9c9e4d8b4d183418c5739c1072230007c196a2f67135591c9c81cd259cedbafe7178f28ed9c1c8f72e6669ab9ca2250c919e29bd71a618f4ce5cf4eed1e1e13e052fa0279fc5e55a4e9989c17cacc46a33e39b40e29580dd07d6ba47716a483e99a02eb36fa3c103694ebbcbe9310516a56ad1f6c0863ee6cb316ab68471ef6cf8612a0e6ab593f85744564a450e1771df0523dc7b3a1e7254a55f1e71dc802a98b8c60e795d1b50af67bbda06b3244372387bd3e1cea4b660a83644f08e9ad4578e431c3b560dddfb4aeb36ffa993b411df5bd9dcb13de404f818aa051bae8fdcc8c10190d4f0c7d398a0743ca53a388120d5616042c0b1ee79821e35b7717f021b2c28e871fdbe5a4c06b1a4cb38f4b3950604dcd9791904212502b91e4e4b39c9b805fa7257dbfa632ba272ab4de9cc3fcd0c4baaa5c231d959ef27d68b9ff3a473176533fcf5fd26c0e90b7d5d65d4f8a4a374343df23e823cabf48dc372f7d508bd2eb0454a4ad59061cbd1b0a57e777f2473ff769e5c91b3e05af375fc5123b55bfe419e975153193bdfbaff571c0e7dc2df2e0d60738f8214a43ce6eb8880f2da4ad6a940143597eadb4b6de022329456e84a8b5e4e93d9fa9ddfe040b107ac21e4e6178b0eaf907114472a5e400000000000000000000000000000812171c2329", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 83, - "comment": "power_2_round returns a remainder of -4095", - "msg": "48656c6c6f20776f726c64", - "sig": "b35a9d26d3cc6ae8bb05acf2044555aeac041165b78f65f13831ec482972193f4ce7eaff57bc166a11206ac59e51f798b7a0b3776e447ce2941b99a4e0f6238a8a5f3487813e1cd00260127a67f5fd09222668f3edd5db27f9f9223417f82dfdedf9ab5ea6ecbb325f2bd4669d59a2bb8634f2b658d2d3362a79454372e2f31f81e6de020436f9bc21db4e2b368a448aa15204e170ceebf7b767290ae3634b094e569375efe46b71c0ceafc9af5eab65325403e9f7573323ecaafe5f0a7b34f3de08f124da2e2075b2295d2390b41c737b48767782a83c09d46d7ef1cfa8eecf154d35cc8b68fdd4cdc10c04e0470953221962cb98ec479d80461d9608f6f489cbbd6266b05266a52d99146d76060155a093eac3c3580aea48f183bc95aa2b77a00bf5f110ece9fda38a344a20eab6be2830006fcdc5cc5ff247c357a639f665562a527a99fd1c0e69b37d5ccc50c65c27dc057d6c7be4f970b01057c612101dfe9fe6bf23b621192c5e94a8b411dfc3bccfbd11a94ae05869f711f1fd8f6ef9b7f9b1a9e4173b56c99b05bb379865ad9e414fa44e6ba4f67ab4d93fb045ca0316ddb9fd92d1ee08c3fd8e490c7e533fd1f761355c72a37d9b7d4814efcacc66c8af043560287b54004ab30b91c03d8a510cfd5238cf3ef301d8efb042d331e3c2ea48876b9dc9b05f2e941975d247defa4f8cf2c7bed438ae680fe52ab144e7bc9d0926eead50fedcd7aac60fc342cf566671e84b02285686a0e9c49e5e05807a6b96df521c38905ba9079e9aa6673a1ec2208f8b2dbf03dab944e909b58ff791facae78e429a60dca239df3e00d48fe4848033d35b5847fb9a78b3364c9b37b7e0a9f3c497e811187f26ccb57db5fd669dd4b5bf127b5f01e6a9285b607823a82062a096e0b8911f7b0543aa6fa36b0c2a5f29fce780cec024560938c61915873beb6bd642d67d609bb43f9d8b8a72859fdb13f42f4f8ab60bd23725ddca6f586501e929d9b889dbeee8955be8d3251d41c46db3ddb75b880210f447f40c6dc5bbc52d22d2c4408d68a0d8a5adc2a2c9d7348569e858c9fa5254a03f9f1e973c66752c6fb0f09e32e8a587a56107ec4801d7c1fbe2b9de6db7a46aac7291d4081a53c2c6e9b1b0afb4d5204961553f23dad621bec8078edd3031bed2651f26eba978c2d9e230083d61f054548090b8fd5f9a31af5ef2fc2f5b7e21345169e869cb8d2707d1f7dea43f1770f153d50e03f838c41ea4eaf4679d52f23c6d41727c9922bd611b185bef46a220a0a76c7ee1d45cffe889af4331b9f6b9665830ffd9b3fa335e4d0d66bb9f1d835d7c123abb334daee683116de8e4342d11ec42a834be306f1b39ce24d9cf838f7fc8ebe939abdae09f8ee7c10adc56d26fb6a928242537d372890143605bedf8c601b031fde9cec47bef17e4e54a5d90e470cf4e826fd69193e94a21e32979c368fe9ab7dc1e582d02759f7f6b8386f4b005f3c4e956ab528b8436714a132c667ec0f21fa9993d37624d8bec1d9d759f28601afd8c7467247c8bff3b35d0fbac82604ef25e4b88ea05f700222baf0b633623467e0b191d88c1bc550a1dbef2813df92556f48c99cdd22557003c3c8d39cfb91316a4b13a078afd5d52c5a8e07009a88aa93ce463318d89a1cff5ada0d1609cf0df966b0ca14beebbecd9079c09467c1139ff8ba25adeb114dc51f662d76105cebf40ec1ff82879c8e3a653343add75ec4d75ddc6f6b76ef85092085b8d121ea81d875b362d95c4e28042df3958f16c7218215e9039c1cf485ff3154e46d3f9825a8e1f74e2134dddd56a81d8c1a21121e2dbaa322926581cb75592b99c9f90568f9b6e1e36f0fdb3a9e5dba272403375e42f3a32342354a798b26e8f295a9f377e022be8485513bfe6cc05f896cb62292acf714dd81d1e87ad89b38bab5532e337b2f326fa6cd508ff2760bc2501d729a66d1ddfbf9d622757c21b2a5308143f198eb02035adf90d44aebcd12fb161515025198a26433c7adf75f6077cb8a536826e18e4b80964e97c6354455306f3c5b6a8603c7bd2302c20faa46cba18bcd57437f474939643d7c25422ad36e56c3a80cf78deb62d9ef3b2de60ddda3a6c080a39c24dcfe88ed6a5c974a5dfef3d4b524d425bafc65dfcf4d045a1d21ddf393c73c2806ed7200a86ab718655f8951a1516ee527cd407baa36e27c72e97503a3280104d92f8248f1cb0c6c0d91b262fa39b8056796f954150d1a0911cd6c7bda3870ef566ded8d656f2ade63f13c62aed5087bdc1469eeb64418ce7af5fc50b721575e99df25432804306a89fd33c0406be8beafadc28f533e12d05bc3ffded1dd59cdfaaa54bc8dbf75b05f72b3dd555172666faa87602411ef6d97ff3254706b876844ebb3948f13e62380df05f67bd13eee4b8a2d7fcc53263072273eab92f8b7bfa64371b58a412bf5dd806c2b8054e8f6efbceee0700e20f6e4e61a6fd6dfdd170fa37e6559362e7b56c9ab7e27cfea2bbbf19c1815e1c863fa24c50ed465aa12583b345ee4007e9677f5f582c9f9377e5b0b12f34ec4e8f4199bb7a683142f07daa27951466f9d608389c17c5c50cd99834e5e975304e2ea1f6b6aca94a433294831a8c5e14dbe46017932035041cee0fba54f87421fbd14b05454543cb2e95046080da6ddfb81aedc37e51d0b1c3b6d036f8d97f8ad4e7752324c8bea832cad6f8afc499b35164b71f497d86d54c5e0cfc67cb31e01a6de5cc43b42927b20ee57b1267141eecf85bcc94c5469f68176f8313a706b2b1ace776bdb69c2fad7fa383dda1895c36836da08676a1a2ed697843f135c385831795ee32a5750fcf08013fbffba54edbd4ed3fafb6f5552a389a56f41f68d1a721b7b344f9e74028217c39c3c2aa1fd9b44b90173de0f986a3e2fae6e1cdd3458446518b2551a3d3ff4294dc2c217bfb8b281b42acca144fdf8c1ba08acc10077c06dd8cbd5d4ae2336cb02cc400a1f49ec581d1e2c62e1cd21be275be4257105836aa99631041b999a16d6d57c1bda6399aa50adf0d4fb8e1229d8531aadc834daf90408fa2120ccd2d39df7f93ea12af0873df00e201b4bd6851ccd931a23e6589f4f583772ed426ee324105d72a05e308401cdb99b283c93cc518ed7c98f230d3605e987b79f8b20d28f99c46850c025d26830dbfee8230234b3efac3a3ebcd322e84c604782830397697bd1308d07d24dff64f7e453dd0eee7161f7e376c7f5e108e04f22dcafa47278be38a4754bd7c9b657fd9aa77a76cf9889a2e6f0ddcec106db418d7329686bba394ee09c23629009bfb10b360f649e962cff1b0dec8d47016cd15a068a5c9d8a721096a61e91b00bc28816f96d4fb7229d77c4a9b3e23ee56f12cc973bb0ef158c0bef405bc6483797aa1d4eb1cc7b2e1e34365b99d3b970b8dcdd7655d143fe6f4e191b2cda90a1e6158f55553af987edc08a78355557c3c36a2fb530c5badc5fa786e6a4feb041caef1fc0e18283e00724362305ff84ac5478b4db29859b980f680b1ee2486d07ce2d2b50264f693351d2c7e03de1922bfcee5dd7103c9b5c3f5426141f293bbdf920431e639dc79e63343d48480354204e920bf276dffd3b2692ed4a9654c294e1c0c3a0eeee84549f227250a4bfef594ea0c3a68bc2c6619f85d0c96b01dd05a9c076a7a2cfb6d0e3dc616147d3e7eb7006f2026040ca208351cc2f3fe3a7e72d5f2ae2c18ad5c80e1d87d439a1afb4672729ae4d04ad517e5a5dd903fc1cb5ed3385a11762b5a4e5d9d7fe00135e6857df3bb623cc5963f0573d858a0e62d31d5ecd54ca5eb4f1344ff1ba7bc2544e7140c5a2b9c3b604c88f0253e44b31f2543ef0e682c5a50bd2933f8bc22debb3802625fd8963d373321a0088cb910f51762e496f50d822b9d445780ad78f6c8143dad25cdf555f6fa49eae6841fe8e721437c7f541ffff6596b7b52770f44cbe33e1ad00857a8d36c0ee20de9c9e4d8b4d183418c5739c1072230007c196a2f67135591c9c81cd259cedbafe7178f28ed9c1c8f72e6669ab9ca2250c919e29bd71a618f4ce5cf4eed1e1e13e052fa0279fc5e55a4e9989c17cacc46a33e39b40e29580dd07d6ba47716a483e99a02eb36fa3c103694ebbcbe9310516a56ad1f6c0863ee6cb316ab68471ef6cf8612a0e6ab593f85744564a450e1771df0523dc7b3a1e7254a55f1e71dc802a98b8c60e795d1b50af67bbda06b3244372387bd3e1cea4b660a83644f08e9ad4578e431c3b560dddfb4aeb36ffa993b411df5bd9dcb13de404f818aa051bae8fdcc8c10190d4f0c7d398a0743ca53a388120d5616042c0b1ee79821e35b7717f021b2c28e871fdbe5a4c06b1a4cb38f4b3950604dcd9791904212502b91e4e4b39c9b805fa7257dbfa632ba272ab4de9cc3fcd0c4baaa5c231d959ef27d68b9ff3a473176533fcf5fd26c0e90b7d5d65d4f8a4a374343df23e823cabf48dc372f7d508bd2eb0454a4ad59061cbd1b0a57e777f2473ff769e5c91b3e05af375fc5123b55bfe419e975153193bdfbaff571c0e7dc2df2e0d60738f8214a43ce6eb8880f2da4ad6a940143597eadb4b6de022329456e84a8b5e4e93d9fa9ddfe040b107ac21e4e6178b0eaf907114472a5e400000000000000000000000000000812171c2329", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Tests/_CryptoExtrasVectors/mldsa_87_verify_test.json b/Tests/_CryptoExtrasVectors/mldsa_87_verify_test.json deleted file mode 100644 index 5b86cf18c..000000000 --- a/Tests/_CryptoExtrasVectors/mldsa_87_verify_test.json +++ /dev/null @@ -1,947 +0,0 @@ -{ - "algorithm": "ML-DSA-87", - "generatorVersion": "1", - "header": [ - "Test vectors of type MlDsaVerify are meant for the verification of ML-DSA signatures" - ], - "notes": { - "BoundaryCondition": { - "bugType": "EDGE_CASE", - "description": "This case exercises a boundary condition (e.g. in the signing rejection loop). The verification algorithm may not notice." - }, - "IncorrectPublicKeyLength": { - "bugType": "BASIC", - "description": "The public key has an incorrect length." - }, - "IncorrectSignatureLength": { - "bugType": "BASIC", - "description": "The signature has an incorrect length." - }, - "InvalidContext": { - "bugType": "BASIC", - "description": "The context is invalid (too long)." - }, - "InvalidHintsEncoding": { - "bugType": "BASIC", - "description": "The encoding of hints in the signature is invalid (e.g. non-canonical order)." - }, - "InvalidPrivateKey": { - "bugType": "BASIC", - "description": "The private key is invalid, but the verifier does not know that." - }, - "ManySteps": { - "bugType": "EDGE_CASE", - "description": "This case requires many steps (e.g. many hashes in the matrix expansion, many iterations in the signing rejection loop). The verification algorithm may not notice." - }, - "ModifiedSignature": { - "bugType": "BASIC", - "description": "The test vector contains an invalid signature, generated by modifying a valid signature (e.g. flipping a bit)." - }, - "ValidSignature": { - "bugType": "BASIC", - "description": "The test vector contains a valid signature." - }, - "ZeroPublicKey": { - "bugType": "EDGE_CASE", - "description": "The public key contains a zero vector. This makes it trivial to forge signatures, but that's none of the verification algorithm's business." - } - }, - "numberOfTests": 76, - "schema": "mldsa_verify_schema.json", - "testGroups": [ - { - "type": "MlDsaVerify", - "publicKey": "17a508179b35057099111733da28fd1a2265de7d8ab22d5279f13bca84cc42a5b8c9644c121e7e1b81723c5295be288fb6c36bfa188b6e08d913a152350947fa2c8ccc3fd01b319f65a2058a1dff54133946cfeb408d0b6dfde6bbebd7e0591cfe83b8b5452ceef6c855f7d33e06a0d269345089ed0d3ad67d84d8a4a34d16836004cff125469e8c3387abd788b620e30c1fc23909117a0e34c42a6631d9791347b1b2a3c9ab3082416211afb7bc3f6ce630a7019af19f736cdfacb1e7db66b65ef56844d2a2b0753d09283a7a0b66f77596384e95f7ceddd1c4ba20edc11f1eaab695bb963f6eda1c383754aa372a0d7729bfa6e0f142131c2367ba3f89ce3de6c357f9a7225b7cb85f6b3e8a3a122e8501fd1446b8152a415c19dda1d2e4590cd994f6664b4d1abd7381468c3a085abe2741a0cfbb81880664b271677245c4a471bf8bb8e0192eb32e4fb5e8560f3c50d6b19a353e486d0fcc2a35ac046286e707e095f61786d92212686a65d39b6863e0f8cec1e1997f2f845e4878ca9df650c746765296790863e51d012d32dffcbd746aa2276d04c0a57cd1b3d6ed06c0d66a0897aae5c49c97b6f19ae829baaafbfed28a52c05963c6eea9eff69528294207f8cda75280f7c486e6848791c8e37015479f2e13c28a9fe654dbde11689875203aaec51be3da7cab1cf31e4ec476c0c830cbdd04ac02167c0a6fbfdd6548b1fa525d235c7e3fca8d63e6427503b0a45c0bfddb428b837c32e8755441077bfe1c0142bac357b012a46545bf4148d465472dcf89c9d73b62357087e229f53a450d3cce41c8ee21a9d54b61e34a794f5b1406a70724ab0c3712c49df231ef30a956075e907c51b63dd1f9453dbe60e25b0f3cc0354dfd7c9119313919e77cb2c92f544d3e5302b8827603e936b567e99bfe9904932585a9f01a5a1b5bce07565f1d84c6b1c5c86259e1fefcff18cd06861122be6836be21e40be4eaf6bcabee8f634f95520aa914bb51c54dbd67d1b9dc5e38831e786c283979a963a3206b98e339edec4128b0502d4d47813869713e431a529a03c7f54b50123680f2b7f256f5d2b40642203259b9e85c62253d5670ce372193f28b5aa48ddd643c54756a2cff808c109f74772961d8db6bb8a17547c8f29c7f5ff3ea06740b867d84917e07f3978ad0281a20689eef58467e768b6178a9b36a567289fd39762bb3e4254031b2798a4550857f6af369d484392cddd7b48eaa2942e2cbfe754d5ee2da2b7fa71222e4a525ff5224d551a778ebd828e4e0499adc74ff0d59a5abc78ad6a8abafeedb3c99045a14423507f85597b1a7f540982f7d72ea13449110b442d54b78029b4c7fe3b49396dc6c3b7d58792538fa907963de10a4b724548142541cdf1512e0f7ff1b10a93de63541b8cc3268b4de20ed26739ee8973b6507ebe48965602c35fa3f7d4278146b598d7d7044e16e97e9351f7c51ac25573b7232ae2432638e9166190e7f7a7dcb5096ecb5d10017cdea2a82b4f56c7385041c6919a7e36e11beac77ec3f25df44e7b596c1542c1e376de3667c0e903fe25b57c338e9d93c5570c484f0ddab4f57d38f292b23599d9efc7a9fd9e078aaddca0acb1a196d6c45d3c8be6f39e8cdbe3299e370b262e0bf6fb5f005cae2b12879289d00bd8039de6a571c310d87557f5c9a4f64a0bde7177a8464722a04bf87fa2cb0e312d4fa6e536c61d65dc2c1baf144b0d1d1d75f4c860626ff773933efa9941d105c53a1d92c4f7c7bba4aa969590acef1e50901870f59715ac14d9846d83871a77367be57c63f88bc2c02eabafe678f44925a3e605979282fcd3f284736a1d346c033cb782dd615e886683fc37cd87a91422857774c63c6659096eba393c56225ed8c3485b4f89ecb07d53526281a6426ae7d67cda52fec5ac32320caae9b96000bcbe9e8782be88cb1ca6dcaffb74ef04c77e03a994bea2c89e4fcfa44cd0c9f4e30705a8b7b20df8c76b05a4479400e07db03d243e9fe4c90d34e9245f1e574be9a388f5355482077e4e98b919de024e666fdd7d51ed2a0d58a823e7497eb07303cf1d6d5f10a536be980220de5856727e5c13981839cfa19740988e7771a2b984f53ae3a5916ed881a4a90fe524f0bb3778355882864f8961fade32e656fcf9f524e748c8196a1f1bbc57bf8da7b36de9b0080f0c7bb8487a2b7bb7a81a8ff43a2539b367c9a48c70041520f05ca3dae316dbbe3118218216f52b7bcdba7557c4c9d861803a5e2ee01d3682e1261d7cae0a99fb8de909eb2bc1e112aa43cc2fa9c76a222bd85faaaba5d9ec2198ac45a295181a324a0592632b89e2752582cd5e01e1a610e7563faee10b76d853109e257e7c0c248a9fb7933f514b07b4f4e3a4a3d2cd22e8cc45ebda3bef5948aa050f01eff85ae98d19f69c51e67ff89f2df0c5268acfdd325e84591317e05cab4f9e6358f249c4ddf4019fbc8f511549a733898a50efa9e0793083de0b15b5bf78d9f63d8df830d42df2fefa27b89e0ede2a702eb9467118fc0ed44edc63ad1b1935877c34843fea06fdf388bbf83e501723a13cc6cc2efbb9691fe28fc1d45270591e5bdf7aa1c82673544ee29d9e6c9da3328f21e9729bffd7f4e56de585909679a74037105fdac3f51ae35f69d9763d2e4cfeb1d4a8fdce99bf1aa21f866a9f523b2a9549e12258a4d19900cf5db37b67da19b23563bd1d701c6106fccb28e4689c62e1a6cf1abd763d7239c2258b765610d4478be9f1650cb8d18923592ad0024076e52f9bd0a3894fe97bc0a1646b4c37f62c27f32d0df270260f47c49a5caf110e4cf80168a7d54b1c70bed9bd5d9a143ce869a05cd44ee266aecd6bfedb39be79e7c7d5c11a99575ebc0f389cc55a4fe1469a2d61b70bfe4b74e3e27521a037d2b9f4fdb377231e2ceb214ba90f6953865c683215203ce963875c6524c01b789e0389a9f0c386eb236f0dfba6c95df4f28ccc7ae7cd473f9dcd20817cccdd211bcbc78b064e936e4ba2813df531128428ddf410e6ca07044aeb4cfcc0a16c995ec51c8af16a541ce18dbeb69a26635632dcc24ee52a5eedce38c502cd0e356ec31341c893f92e6063c3a160a53d34b85e92357a8ebaaad8f206771be43ee48cc409825a7094bda529ee18776d9e67f1fa1c1419514309d70ba2443be2f63b6943478d6c0f56dd058731e53de4c30bfc7d915e9284a56248e81944392881666680d4991f04269ec9a83b24b458ed59a6c274de452ab3013c103a4920543e6a7d22dadfd764f6ea39d49b910ee0dc216e547aa5fb4382a72a568ebe83ec00416fb5830dc21c24ae72416602870cb52c3a8a1c4c12a4b287b9b800d31c287ca161f404a9e598a5358d28b3aae43e534846bcd0d7a9c7652ae01e6698c79e315aca8198f36de45af7084b1cb21ca2ba0ee3a547a7343a10ef9e3fd17b0a4060badd1409a0562cba25b84fd578268fac53cfbca08e6cf6e5419f57262eb5813c1d1324e0df1d483ade08d8f6c62498e262485ac7c2872b11b42e5c1b797fc12e838b38a711d364d45cd1ed35f7faffdf4b0fb0eaa312fc3d5af77909b0649cbbacea10c9831273922b5b05172face9ce6cf324edf6e2f5f5fa0a9f0463eee938b30adf3e55664f94d274cd87dea901a7e08e805", - "tests": [ - { - "tcId": 1, - "comment": "baseline", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 2, - "comment": "empty provided context", - "msg": "48656c6c6f20776f726c64", - "ctx": "", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 3, - "comment": "non-empty context", - "msg": "48656c6c6f20776f726c64", - "ctx": "436f6e74657874", - "sig": "62217e84cf857b184906ba906b223394356d695808a3beac5c9df51dee7b21500679e5b9ca4e4abc35c150ed56356d3050f559d54c176f57139afaedf4b688d440f5db3eb9e5fc6adfdf9767a53ca1db1e74b9072bcfefae88b4d0f2c6de415ef52621f4adb28ef54a0c6e86049548a5b2152f56d4c394114bd088ffdae4fcbecc2ada3b0ed796b5c5e4e46ba101d4082137d93c9d0ad31c5e6117cf4bccdcff664b0d284c994d9ad7a523c9eb202df60c5a1213489af6a13cf4870d60825e41ee282f1012cec3a69edab1c7ab5747c357fb084c699a6f02ba11728b25de7fa9de00cefefe82a62127dbed26a94c4618ddd47e8f781c21c38d42c5c29ae7e0e4250646396bdbb9537327e1f13fde1e4e5ec2aacfbab95204f9a623a625bb4bdcf04acb1c26f36c77909468c733bc379e7c5d9aabdbcbe21ec13c955d461a6721936d7850e2b13bd72947493af86d7dc955fadf1963dff6ae298606ca365f9f89d32c405d8783cd9450a0263733d13dc71223a019fc23b0bd9f80b031961b4088f50b04eab8000bf76a550f28058e6f6b9f5464d8c83d3114223dd29803ec0e4a7af815e21d97a6613bbd21476bd383792b3d3d65eb7cb87b3e18a883ab2051e7d8856237859eb352a24525f48258374615ed9983d3a9f0a30295d6f2e43919ce321d8508796646834d16803eb2185de0374bd61f3f0875e569635380bd063e5a66145289a80ed002c0474b4dfa8e0a2d7e3659684e2a3298fed67e53dd75f3024326076d3df7bf0b8554b46e271fd2c1075fd86df402fa2069964d1748f44f0fa79931335cf2855724f50ff62d72e316a06a82d85a7a1a588291aeeaadcead38c53f1cda880bd441caae66b2588bb93c18dc5db8bad4eecd43859ab2038e5eb151061fb78c6efd9476c0fe2ce070d0b0d832d46a3dff0d52d585c71add41e3a62f4f8b0f70818064bc4b06ce7cb239186b50fa687271056786b52a1f37be5454550091591aa5cc84971c5d8f1e4b894e31e2108907d0be93a4497bdbc668efd6abc9ca9daf86413a4746288200486f2d2c607d5f09c8cd7a1bf9484cf9335fe5d06f60412563e79c41b80f3e56ea3e02391f1c4aeaca8622694cc26bb1fb6101b199f263ca81db6a75d335a814389e5df5c12fd00d510feea725a9109a1adf00912ec7f2356e55b96ee7303561f0fed9548487fe3633442df5cdb61ffc33080803a8962f413159859345871b17183e783cec8db3a2ada8ea3d55eb7ec73161073d88c654e56754d2f8d1f421048f1046672017e2229e17df61f03109e993a02102e6807f8756b0d1ee499131ea0ca8d4156004a6a0637788bca407093ac59052edfe0de9dfc53f50f545777d2bdc0bccd985013143fc464595f084e67e342271741ce38a96d4c4e3c4f6f9239aba9d2ad5c23f1fa8d7bfb60b83beb67436ad3881ff481543febebbee46f9e56b6eae7df3ce8b1f1203c38fbee440d6a51edbd10e4c8894df60312ef3261949c9d79244e47d5e98c4ec23c10eef7459d01d485df2d13403a16949df5a6603c73925eaba5fcfb49d70acbdb3742f45725f50224fd4062516b04dffe6845f78051f94366b0f78e9daa12cdbc6afe81434b7bdf9a66a81a2b68c5aa91f8dd6f02a49ede5f4e5947b33ea072790dd77159d7caa71ff67670eff0d164b1cacefbe5af46c68cc124e680f74760064df229905c670bb573a61c74dc8d948b87dc948d5b12d6327cfa3ac48270c3713f4b96ce7b9e00185ef74effca6a4994dba8a3712a986d72f8b95d00f4c17022c1ef97deea0346402723d62f8550037a604d8aafe6cd0a5063892449e94693e53b3a71dcbd9c94d8f78b1eaabdae982a5c7a23aef2b7e055851ff53206785c6270aa10c3f12df291bf61140b38603dfe75179a47736bc069abe2d115bb74585b86e2a449ad51445123eabc54070a42719e67f75c2fc411ce3d05141353cb33da779b0fa6e2aa6f9a55da5edbc85952832a39ccdd973fc7fe0fdc5c5ec4bdb68913ce8f2580507e3b5e16c4c981a14c027b8becda417cb1a9428693e9505e5a0cf5d9afc1ea715abecb49b083d05a4efd5e717bde7cbcc4eb74f3011ccc28ff31b9a74459d9fcf1d036eb78c1c85b4e56729c1d7e5135b99b89a8f238ab69b7d730b3a47da559ab45e004d844ddf7c9444241df1291e00e89e91b42d93a1bfa1168042819e28758c5d2b45c50870ae4e1d3f7a05510e72f422e684a29d71a7ba484afbc24026263078bc152446cedf142102d3395ecc6d32e98e5e6e3cab52918cbd86c11b86dd3d80c4b75035e62ad78474f5870f0fb9f421e109f0c3152891c070989d5ecc660f3c9b1bfe86694b7712c4b63cdda78380710268a72c87275641c7236e3c7c40b368f53c98d708794b469b1e19c728d2ceb836262d15f975d14ae5c822b13c3a450e5c0a4784b7b93949084597ecc4f86a06960619e92fc3f5ba1e71270f0f5f8ca6fb35aa9fad66e93c3b169af95572022900a3ac4507c005d518b7727639cbd6e315ca0473ec98cf2975df8bbf7f2ede7090801cf5931c396a5eb123a1c73471c5483fee67948dd28e5a9e6fffd612f59323a39cc3630b43c0b66a74d610236aceb442cce8c67c051cd1b56af5f299c3e90a82848eca945602289cae9ba4065e86b502147c06e8c7b76fc18f6ae33a27a1661f60cebc713802f43ebed8ea8867c69e97d4fedae2679f88579f7bd9cface5ccc1bc48eb0095659dff03f1b0babeff8a09f36e7a29a9afc69965e7b70f63c8e7a0c5da68ef6bcd074a427941045fd96c18497c124f5fcdf34b0f17b29b22110fad3d42a6399cbe6d7db7e3b0a93c3b9e71c068a9f52aa70f677147689fc79e367edd5abefe23252a4536ad1458abd91916c28fec848ebe1add87a9e5b63460a04163dc8af8051b24193b1d38ad64740d10ee2bd426e36548edb8183e8a2bf788b0a8323217ec286054647d1996f4f88772f11f4eb64b64d0a240c332de938756a442ebce2a6602c01bd382f5c532a574c5cb3401187590c83f84708b72600e87abc0e77a1093b5d0a70c8bd62067a7bb7a2ad7350c1543817c62c5bfbb6fd3b45fee0d77496ff7e3a8b5945da9990fca764849257f4b95f1e266b8fdf433fba3815c250253def569dae59a366d6cfec2b4b07c907fd48dec46be900505b1cf58f0c43e47bfc9976368887ad85bcab920f3d5ca37bf28b4a14b463a61f71f5705607077d8eb7a21d111bff390508367c05caf85bfa6b91fdbb78902b1cc27e24ed274c456f77e8c08fa6086c5473c4097241377d579e0661a0e5d0c220c2f1c133019e9cbab3d49804d0e1e51379926d65dc28a2a77e3227b3c8574978845d68bc8e3a2009c1f78cab1a56a5bdf0e7101c2069e9f450aa2d671a24f8c22a97b7c505e58a8d0f584adca28e082826c6b35b0510966fd7d8d654bf73f55392eb3c29f51a34156f94e63fb563c1707fe4f0ec99e06e2d6e61c7390084aed4334b74a24b690f4b3078bc88ca62c29f10065cf23100c9fc9a74ac389b2ccb112cfd9c7f244e306d7c18ad64112a7fb97721b256fd4a740841a26a4682f34c4b739f734389598bd4c03d910c3e3ecaab5846dc3f7a6cd4c04f8e75ad7a7ebbbbdd7c88856c0d9508c4fd17e4348b8b6d37b3baa849c1bfe14ff7e616d3cf8fb9f25e41a9c364a77ffd47e17eb69285bd1e1d1588e7101a52cc67ff28d49f3f679958f1f6557b02ac52d459d9402ce167ae510f07d6823b12c5ab53ea2ff3e8b808e14e7617886cabd14eefbd5240170acdead50e240a259c026812454c242f63a9705ab4b25edd5f7234ccfdbaacc1bbaee7326666e4829010723c0bbab7ee0b4adf4f063e1b71f531f7847ea1c336d42358b37d398795a0fc5f239aa36131af6488eb6c032f2f2985073a4ec1b2ee7820c53ca42c5bc3dc8fa2fca0b460b4e4ee927885004fd2776670b5ae12c927c6a6b9067132e71eaba5d28981620534c6f97086a747eb8489aa0fb33b42ed74aacc0c01fa5619f48d8cc35af60e4d28608f4de93798905b3755c20931b9b190baeabb2f66d40684124ec44d467b474c55e4eb7cb8d6ffb31fed60f431da8ff665da4f8bb878570964a412d72e74720fa1fbfbfe11dfa6795dadc7db02f9ad62e6f93d3da8c1948f6664cf0f723f944741b83565cc2a78a82631a806026db5c4ea68f322c03b722812aacd56379833a14b288725502603bd540628808f9b6b0d085aeb3190a42a4b8d2d61b7ee4da8d68b5f8cc21d822a3413fa21497f0700b41b98fb6ea0ae570572a4b8a851dc8f8075cc2add19485271278d9f3d8ac4aa04175e65bb3278e33276afe0373f55e8fe67ece00a11de6ce42eafff13b56d14edbff5025c6a170f592e45608c8d0651e5026dda50df3afdf680486e5db5529834bf338d580df00f3f14d5e59565575eeb1aaea2521415a6926fa4963b16488b17767a279d457877cc71c6bbf77a636507baa85954bf889fac3823a3e6350e48d151b30311f5f08376f4d153fbba6dde1556ee9cacd47137f20112196f99e33a2a8fc2334e10b561c02ec70eb863adca5d7a988f33c00fa21473c8c2eecc8332e0b05ac4c6407e5987b94985b72531dd945391e4720fd0b33199e35866c9b68d88664cd81c9073af42c796d29fa8b575379c44336dc12a18d9faf7934d767cd156fed42c204c1f0739fb76fe11ee69a766be3257cd3cefe40af817797662e4424cb9fc7226eb23f14249bde2ae7bff15313d47208d72722b46a7042bddad08522b77c0e04c200cff19dcf78ecf34ce8763ddc95f67c01284887a3b3b45adaebe97040ff871f336e37d86f27be5dca7b8c98e95f0f6eded509a4337ea8a2ef3d8313fe8b413fe06199542f8cac04433f02775cd4df62a412d26613977ad7870daeb8f2fa50f7340dda3fe8490858ae686de7ed19068818b57ca9d31beb413368b0a31a247a5d22775c33e1e684aec3f4b696311f2d1cca69f09ff7bc98c4f2e67184affcf8dfc2e8f55a643ffc2666f13d669dc7f999dd75f722824fdb2cdf388147be3c1b72853160214d1b4eb0fc4c3563df53f6f848161de8643979853c32eaad84e9abaca21d896aacfba9c10f79f709afe4845395a5a6114a9b8424ea67a5de6493c295c1c6df434fae8a017163c7e355d46dd7cfe4a2ae8035900c280c2f347faf62fb503d90673e812081296117f1195e67121c6c03893ed3a784a0a0c2104838c8d179e07df7803528ab6186034c68e24b362b752284f7c22a73d73189af93c4cee07c87ef2bfa84f47d04ab111bb684808722e6aeba4b7cf593af4a0cd05057419d2752618d4f5a0a84b7a75864dbeacb8c78d6c6c94bfebcf29eed3e543c941f1a912616db4551b39a12a84f6f43f89244893a489b15c1af5e3a2f7af01975101fc6321564561d056740d0898a1597e8795fb53eb7cd9f126a992e136ed014ff506287e3d2599cb520204696508bd00c66eb4c70a78e24df1802db88448519eebc4f3d09cadccd4c15b0bad8edfb8181de86bbca1cf0f8b07974676fc5662911398a5168a9eecef932f0eadd9a6bcc26c1ba5640e6a539f6b64692dedc96f44629e74f1ea8bfd23bd66e6666c06b7146ac947d9147b724a1f2c0adee7e86ac1110baaf3c430d1e1d892047c5bebfc3fe47b0bef928141213b943b1ec1ddafaca1b0bd48275e9258ec9449ce4fd1e7d2491ca4a6fb2bae37d6a9e8f67581c6bcbb611a8653383518d565287218c53f250c3e7c40649815f6413c0740b1be6021c4c7b2eaa19a0314355175f39b07c695e83cc1da41cdcbe1e7851db91814f8c3fc2ed9f5c192d696e75109c366e426e4486a707cf27f2cf48fbf1acc38879cc846ae09cf63ebe84698601df4def027b080eedf4f173dbb0282a6028b99042ddd36e27f78fa05bd279ae776f50d83f802bd39e6b4201c02f753186eb105f00fa089d57d25983798610b51358cd9c344dfc57f254bc9af3f34b0ee56913fcfef914f14f97a91387238bd2bd328ff37c2c9d71603fdbde89014a3cb0f2ea39ae86988d6762f99669b70fab81b353a73e6731c60f70f35a8a1da777f760441a1b24981e1cd98ef070d8b4d095f200ecfc3a085f6fa5cf6b2346ed90d8e96e21fa207dbd8facb146e8a3f23964aa6c7c1b7f124ffc2f77306fc6a504bcba9ae2dde7b12ecf77b4370a4afaca183e353b966345d092d254b5ba34e9afc3460fae9f4413bbd58e2ec8518bf243d50f737feec6d167914410218be4e2f9e83de9cf822039bcc4696b282fb4a6d33a6f93570133ca5e1d1f54d14025a1813fd74aa587ba7db0f0974170f28ae378f5d2b2dcaf8d412b75e8310f2c0a92498d4e0211b1327b96cdfd648b3548e342a96cf3770681981d20dd69b2bb404bf615946c0de26cde04666f8ea0b3bbdae5f5f61b25515cb9e7f244496d72536c6db2c7c9db093339418a95deebec3337445391989cf60306101220b4e3ebfafd3a464b577f88b3c700000000000000000000000b12161d262e3840", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 4, - "comment": "longest context", - "msg": "48656c6c6f20776f726c64", - "ctx": "414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141", - "sig": "826fb0bc0a2a840e59636f05b41a8c958b1d31df1674a921729043af0808b8abd0e2705d58303b4cfc8905227f47f7024d268a70d3ab14649408c6bb8a22f2dd433fec0c24d99eac08606afa025841fb0e0d0de189c803afee4fb5583f66f7d539fe5b9ac2ef43c17fd5b67571bb7b6bb5a8dcb09b0bc447e41e99affcdb5139867a82b706a0c8b42096eb39b5b99938f086a0734fba5514083ad85d2f33c0d64c49f347899de5a3794ec8e2ed29430da4eb6d6a699400dc007906d4a4d0b5153fefacda26e23e99d17a7a9153bb4c3cf6b623a4897a0246a73a80db53df04f4d1781c4060578b6cc11b374599f330dfeaa7ed92f1ab98c68599ef731a9aba076b416b52bdd78fa09e2948830450dc83998fd2cd1713fead468176c5a28fc31c0269d4492f429fa2a8eb5baa22a5c5aa08615eb066c40a709677ce8455181ed181bbc805ae1d68ee51b76adbd429bf22299d18a0876458ab26317f7046c828a352449f3eeb0063ba2d778ddd8a35ca6e8a9774f21a289df8094765316bf5bda1541976173a9336a94e9a6ad4e23038c26a364832083300d02fe35a51058852cb7dde808f5e1aa8357c728c9af09b86df5101ab0ac966c48d26a28339feceb7db9e7d9b9a57c71002dd1612234579b0079b13efe2df5c1396ac40d1a08dd5b5a21d90e9863bd05c771515f5033032c0dd1fc92fb8456998d3de20052ef3005bfe162f2b281cfdcc8caf440670a75f6feb74b69ed8c65872571765390b1a3d0c68971545408bf2fcaceec1dafb99f12f1c2167d56782b788bd85920a1fd30c94ac09d7e6ff2298438264880109355e9ea5e3a4edc41d0c6fe5f3344b36f6ba88799954ce8d8cbd04e45b761660164588851be7224ab5f02226cb258054f727ed08be13197b8d9fee7f2150a17e0cfd80a5815145b979c65faac7862e0ed9e0dcb1de4f7f52f2026f54671b7423bedd76399e00bbc76b6749dbeb2a21218a436523717ccf0e78669a56f3866bc60fa7c9c7b28d9a464c526507feb9568a93e877ed719290509374213d1ce0b91e99324f7da68c0ee5454bbbfacbbb952ff26c5059d974f45f2722381927f6baa147b2954dac3f9ad76aaf28834d1621e7d07e7fc8298b0d67e97f41a1ef2cc1aae30aa95db1d7d467ed9bc9bb3283513790a38883f44be843877dbedde1f40343720f4348a4c84d39ca6a86938adc99457723f87fb43face6d549cbc7d0354667e5810684352785b05c5e2fc6a329888c5512c25c9d780f5590ba4963e01dc54545534e12daf6f510ad9bb771453aab85fed1d210313c2db8d2b20c278d4990309216d9c849465ca708470d6d942d02f743032d9821f6a34bd12be95ce6d8bd50a391903a84110fb9664a110c9725be8b54af19b0974761159ede64e07b609f322c0b507a37d9c1101ccfa9660bddc0b417c71895d7d0ea2498b2c9f456de1a78c6f2c3d80c24f1619fc0648e6701a39c8d272d938108367eeba67bfb6e30b50a64fe7a3ead298f986d4097b8e69a5f8048fff0f284f7f0b43ed49a4c11d5e1f062d9637014b4bc0ad98bd41596b560060ec950f19214e5efd3bf3fcdc2f7dea55bf6ce4d1f1609e5f5d97c2ef7c8c2386479638fe9345c3b010449515344eb349c8fd4ebc002736807a78022be036150adfdb93aecc658439bcff3bf012c95bfc5c9db05c29dda0aeee842a69f7c0fde57349bc799e8bfd835d4285d541c4c2fd88f2092645c79b69ec9193017e08cf0213b7020e6467e6349274366a76a52f869de517d02014b94494dad4307ca90b6c87ce209ad284b7ec5289d6b7867d622259be2e4a7e80d1db525c34c21b0a98cea68fe2df54b389f850822c20cd9c4c18e428a2bd50f5256488773f150b8ca584ce8ded4e0931d6f71c2448d6a8eded9356ef08363274b519a7b55d3b5dad2860660614e817bc904f1ca2e5bdfa915e8d3df4f80fad1c64988299b1bd0711e68a15d5d682532597fc1d906d994e737e053c371c757b251a492afde6f9ed207c1892c2fd5be977072b1dbb1538a07864013d7bb88b9f861ebbfb27ccb9cbdcdd8f20726796428b60f17b33c54bf7a69f45b783cf5c97940aa1f264f88d0ae89ee1551e62ea1a918f19aa49aabdee43070d9d67783a560e1fd60434668fdada1469daab397c504ac8eed9a60f28a7bdac3c8d8c12eace7c9027a27f20a17a801dadfa77aa467e5fa02231d04ba399333d18f068372f13d51d80e2501d0bfc0bc08c8e05d88cdc1ff571c653a04361c9608dd2bd7506be729f6432fb25c66b645eb90ccfcbb4fc89ae27ab52150f384e15276bb91136f186be006ee7dd6133ddac5287a6b65264b419755c284b8b3f4eb301fc3a08ce1f10b0e0aece24aa669e17657b22d212e0fc339f655b9ab888e9477e5c0bfc1c113638cbc41319e78e0cc7295014b9b296e72569948afcce6972b31523ca69109511c1cb7263eab2eddac906ce6733ce7475a6f8080afb968f8b6737818ec42654c98dbf917f846088e47ee2b4c2ff37163fd5ae97832ed4989a2d05ad34f7b61f65724b00e465624507843e55dfe04850933d461bf862d27323020b68e83a416a4fb35d424082119c7e660c4e13bbbd3dc691b8b0183a1cc82c6f004c53a9ea1a52cbd256f050c67b45f58b86aaa7b2513d8f7d50d994590e01c3d63a3d20c99874cb482144a48b1c5f097f57ffb5de10f2349077efb1e9d21c264fde6f2e54b906403300b890675708b0580e2018958d18708ccb3e9d06319d505f9dcd5dec17d5bbd63672f59bb33d1b9b905c5d2c8430b3dd47af79d9f9e3279f7971d63d4a679232366698063411a9d5fc285ec26098afec196a36cddfe321a001fec5dc8504cdab6fec7c90ac5c4876e1547ed54ee68d134f2a4a5c69afde1b2e8653b9b41bcca906f678b5171bafb13c23a32f611620044df40b1fed08dfa1a9d16c14a32bafb88499bedfd00185070ca5a549bf9400ffb2de53c2b24c7e96bbc38956d200d0b5b1745280a08c49e553c305e42346f6226711cb7dfce3ce76a4917635caf8819ef5e16cd1b5ec748550c3fca67ad289d5297b72de031a70c25e9bdf6da5c0dc5b2f71e739862c3af9e5d3afdfbcd4bd7ae5dd416ec32300110496d6bd2cd0595a53f08bbf0763196aae3e85af32355d3bda25fa6fd5f0df128165a0420edfbe08f3b48f1bf5fb577a2b03ac42799337ae39f4118d99b9351e96e3835380191e9e028482649adf57bb8a0485cb3c51ae649bb551f95ba758c498c807b1eb2c57883bb2b0cc051f52d24dd6c8596cb66dcc994627fc5dbe912600f1e67d52b9c0a15052cbdf8b25d6308bbbcf906954df300de8a520c28f50492d00a6209dcb6b32e0f16771c72071f58aa77104c1e1efd65dfef07e3a846d90f8d2af069f64b2819a1c5683eb75d99ea7aac645ee255b25ca676bf3cb0178391cdde9909d6e6916ff0bbc365fdc9fbaebbb36c98b246298fe56856d3f9324b86f4db8f2e8d2ec2cdb9b740583a0cec6eadaf5cce2f0db6c68864aa7aa7b208ed8988628bac017fa5335a35963e65a392c9e9cf1c23263d159135a0b91a34b5ae47e9fc79e37b00679196d6355db67f1d90b90f5b4e73cd36f8568f5035b4a57237d856e71a734db720c2f72ab0be00b333c5f75c5076bb6f2bec9dc936685917be97785f709c1006b4a0e5ce5f62d553080a45f0de99079a592b61895910cf73c1e620895360ea40924c827cd30a0c8c6564bb35e0544bd000eba5f3e59e654841010a1be3a84cfb4813256dd79f51ea5c67912a912fe205a14f92fbafebf727f76d81196d16c5deb425825e73be11faaa7b00488fd387f03b0d0f2c41850c066b547c48cacae933bb68f946f6fa69dee76699297bc8f7bb7f3483e447ecb9acb322d0d13f05520b90f9735ceb1d37316da6f14fcec8b1a55fb4e740e17120c739589819504b064bd8a0583d518d624093a7b319db03d5994ead65b6d19ee2697f2b6f4febc87492f508540a1d4ce871c40354feece2a0a64953fcd46e8aa066bb3d73ab351994a0e65bcbe08bc73b8ccdd092aaa51f348bc33275378e757906581f8fea9fb4c63a95ce9a4237311e50f205b3390cdbf89ccb3de24ce54bd8732d0d8dcd41a74105cb0e2dc612bfc9fc553a8523756ff021c43172eb0b8f6f62eaa25a9483004adbd3e107131cff0f1a1e9337ed82bb19a5b36895d1e241ea4a903c45b1a70b9bdea5c2ddfd34df60a71b29e68304cf90e263957b5f9ef2541de17334bc165a8bf98e451c02d33c9be63c2a73dc7a7bbc3c9c15c58eb756f2b091ec304296720b274003954f98fcfe40dee1ef2445bfa7ff387f9e04253eb685c1f5187a23d391f741d097ddf14590dfcf6119c2221da6bb88ad73e85c0a84592c082ed010a65ad4fdcb8d2f978cc1a35ab77bea30ee46a8ff57c353f608571a09e5e80cc21889fac4cd825009ea4dbbe2859d0d788ef486f5ec403f3b70d4262d78296570e6a5541057cce50b86d0dc28228606569b4b33cbbaf3913c4e115eaba91a1c9ecb8d24a023b7676cced3969dbb6ce8ac0186f71edbfa00d140894968783c66d003cfe4154e6de94d39b412094b79fe99807aba58b0406ffab45dd596711acb963bd17f529c33914092541096286168958eee27d3e69bba44eac147e77380e1252142e2d75a3db0c315739ff55bdf51074a1d9e49d3c8cfaa57300393813241017523a2c879901629fe19435d836d5c46e77b42507c58ea6d64fae2b9c4e1af26a629061e2524a0904b81cb1f0304a568df3c38330d0140e4a71c5f3c7bb3cb7bd579f791b6f80ac8225e0d84e2f30c8b1a642c5475313af33d61ed0f5896a33e1440bf0c86cba0e6dfcfa60f68205d666de131a303d895732c54e81c0dcb32f002195037a6d903e63f3091bfe666696676ed0188918a1703d2a88889db851d9e662d0cde1bfd136901292c04fb63a2c26f0b8f513b25a36a047db2a43b58039c5874f385dad552bd3f330b77b708e73fa3edbfab88dfb50df41321d4752df7696f80bf648b8a181772cad2021f69aad200eb8c8ee442bd86e69a8575a0f494f7bc284684c13f28c1ba476ae02a910e5cb166a895df4793cb1697d0322a4156be39c919d609566b28ddd22eb488feafc23fe282392e8b64ebb5234e335f5d52bd7ac8804816840a745cf84a5272229a600162ac7e939e902d5423cc70ef9e6068a069d7268db944393e983eef4a1cabc52a37c46831fe883b6f99fcf10719256305ac78e0b35d9ff25d57f757b8a0470e21ad0f2cb371958258270b48cf4855ae01dcdb0b85b00cd116777101b3d8941da320c3f0cb99d50767b8415d193c880fc94e4804fbb015b00d041dc3b6762f2d28224e4d44e699b3a2d5ac5c03e647ae8431a0b700cabd2bb6f4b5a6b4e5b7a197d49597bfff268b8f884698532ae2dee3ad5811d8e6850bd1affd9f8cf09d6198f909c85c2778e1b611e91829ab479add06d5ef9f582382eb986b4225821ad3ff579ec794052a69cb686f056992f6e57690947a8b2b7d15f389563af0b45adfc84ac2bdc417c4b25a143917cc9b86e4ab8515101252a38c5c4d608259e8d59a4d9b5a121f97a3e833c0f435a3bf79bddef16c3111d3ae067c1a531a197471abec72513ada6fb9f8db83b80e540c2f202d3c035371200b424f0a2b5443f91f4ccafdfb587739822d285fb4196c6b8451a33ea34f52f708be94460a57b38ac59eb2b138827a4991fcfc947ddfb8f0a9910f325d94a363ff4f5d80a1cae0ff8b7ebef9c64019315220a5f10da620f8f92d717e543a912ef8281db7d29f3432d5b0976c747af1268165ac47b1e4c85c7df2946e7d9aece8118171e8aba801646cb804edc945bbcb55798e28098c9cb2ca8cf9606657c1df784ed05687bba93d7bce589ab06b1b94d29864822f193383e6ea3088b630fdc276a033283bfa0362287a8d40b2f6ee42e5ce1b74ebcf5c1e1f49d394e6107cc06e2c1c464cff0243ae09c6ecec1b957b50aa75349d0726a19d4b084963a8e965a4007bdb512c3f49d8b289566c2f714b2bff5e88ee3fdcd1bfbc07202b145ef30441ba63e789f359f7aa5222ce29e578afcf1a9e3f306bc55057ad3c66997cedac1ecbaaa4e1b228ceb8e0eef2132adc20ee05bec2ea0585f434852dff2373482c668b9761e02e4236780bf4fec85d85ff48da2aab4ab447a58bf68601ae8de3058a984cefef7659edf19fc6f6aa5ac9019e5a142632a6bfaa6dea3f08c2ca140add2ffaba3734a091209718a3226f0e0dd4fd6021070229eec02ae3318ee91a3108dff89240f1c70dd3a7c1c4e2f9906f10541ad36950e089d31743c9d275a8b79c2597f42f0dc8787e293b07010ab79c7ece002d78e8b0c97460bab79583a89da2d2f7861351ab1c61bccc1d40566d6fc7f03855a9b83c659eb7bdf9fc5665707bc4d2e707516c82a1ade2ec2448742a4f728788cae100000000000000000000000000000000000000000000000000000000040b0f161d25282f", - "result": "valid", - "flags": [ - "ValidSignature" - ] - }, - { - "tcId": 5, - "comment": "context too long", - "msg": "48656c6c6f20776f726c64", - "ctx": "41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141", - "sig": "fd544d3e34ffe17c347a27e09141e80251e7dca1e8f3d226f3d0afe48bccccb0a2029724a25942de396d66d7d62b8cac638e131bdef8908dae9d0cce2dfec34e912e772cd28cfbb8f5c92bd05552da7bf0e06a3623ae1f2b02beb16c4df832d74c48e8c27fd6b7e67a9ebc71bca5139f5b614e49e7220544ed930f4918c5262eb26217246edfb50eea73eaa85676127bb9bfebf34239e8f6a159be3630e02ad810ccaeaee9035b6b7f464e3f70c2cb0ae60748c1b38201e5f4126ed19964fe960aabebdee7bf5bc00125ca9d04570691dbb037dc6db940d5689b16828d73db1098776905f679d5cda58e67448e8bc8d7215a81353d4657fd478ff19efbe5315b29f94193ecfeed43b0beba9c4d06255764bd980d34661902f58854c58f07ea4677f6cd9c348601d76e66f2ecf9c86a321f06dd585fb5b9cac17a50d18f28bad74b2749c1a143fb35053a546ef5e68394d0024a0587eafa35a23791418ed0c8e14e572bb1c0002ba65ca01b0e08b0e054c8f4611bd73d8888a2c6dc380f384705058f62ddb7d0b8f4844d4125fc4bd286fb513ebf4f1152d225792954a482172a4f33fd57a9f7302bdf59b3ee19e42cdcd3ae27b981b0b902e91eb9e84623f3bb9436a7463253e5d2e2e0cb8a11065d78ede565866758ce5202f2e46ac259e566e9d18b607dc8a6e1440264549df73945cd2df996570bc0a12fd9ee4faf5555896b25e413a5a1aa545d27bdb0bb2759c5f798304010d21b6b4b1d83bfd55ee022e6987b05ae498970990cef890927be6f76b5c7aa1ec3567444334c0a7a9e4f3adb321d5ccc24013552352cb4dc5295ad61c7548a0fccae215192896cc15b96f65fc3ea83cabb505a63ced78ca7cfa1d2e8a12e91d31f10d763373a438cb6e527ec2cbd06cfbd6033895f71ace2c2f091401e420259978e73729aabd6cad8da4e9eb6c8d8e39a789cf9b37e84d1b38c8baf13758dd5a29a6797baef2b54756dd3ad68cae4f7638a803fa6783e8d830a42e454a13e8393d8e7c631ab8680fd5822dde3073f4d2f2e9bcba12a8c1f7282e8a4f19ab4c0ef1f7ebd52f6d1bc278c7d6d1440b2ff2b706893aafefbd2d46bb6e4b49c0c0c1617541b90968876df160373dab50e8e8605415d7b9a509ee8bab502e5144b884ef45b05f64d96cb70a3428ee0842c78220f8e5407bee35c2f2aeba68052b1dcd053c57f1a88e7709ccbb667603317fe9fcc40afb58cd38badc4f0136c2f60848270c6ea8afd4be9ff1d214a8dda6256dfd9d18d793984915120a489eedf31eb82550dae3b7c6878f0e79e4512ed19f0b67d08145627b069a36ddd80fa4a380aa92e6b0e591a96755a783c91d2e9611424ad9f0f3cb66ff3e79cdbf77dcf80c3701e1da0cd1e70a33d5754ce9a3a9843e9d2cdde47f11c65d430399cb41401f86cc78959b42f7b7463de3e6cad24066b6a6c25fe41a75ddecdb8f7d24eba99adbabc864e4d6372cf1a88c09a44eeffd6886a3505835685e13f0c70b63b6906462a9027541172b35b2fa9868249232f97f2d7dcfe48d1f890f77f14f6f16a5072de8c417331952d96f093734e562520d4643f3289e5f276fc3466d3ceaba92fee67b21a2eededfa31f3b5aa47777b2cf53b27afdac507b95ab59760cb284ef231f4558b251f7549f13e48a90876979c71f189ff34fb69f2c08a02259586feef717635d7d10ea7934376a50d8c212d4429392f6235241d0d7ff084c866c3fd76ef73abdb40769cd9b965016beef582f765feab3175e0fdde8b71d207f641d5ed8efa56f9fa8970e472b2f5eb6b98e928493ff2b5ce118bd04d155450f768612515d4809e93ea006a41e881e98b66a99683cf4449e92582ab70059a8963abe5989c3a10301152df95b2d17132dbc62043bfdfc38bdbed6c0eb02c2d2057dd495f7040c6b4446f9d63015ca9013d3519cbe4ef8ebf53490b9336daa650c7bdca437789cd30c63d9a094c1ab6cc7545c615284a6739873fd1cfce2a959b9896031eb9241c6d0db0c7085617fd6512c6e5aea2532600bfc9365b2f9f74774406712cd99d6c2dbe898064e999996616781c9841cb23ea913ebd1d0127f96273ee8cf63f915bb5578852bf02a9a79366e59567f98a438906db881f6ebad5d6f091fe302f5ee5ea36ce3341259b479b847da892a16d67550550a58471bfa880fe341366e882d644e2ae209ee69d1817ad5350cddf65247a57a1a8ed75b1edab2c63550a1c694eb1eb8ef30df4f8be2c0785e13752700fc1bbea959a712bf77272bd77ab46aef133a9e3812139017cb94e19148df5288182ca756c7fde5ae6a62879a72f2120b54f9717703002e71a6d28468f0926f514554420f42feea8c7c797b477080a355d911114cdd0ef6d6119fb617da1ff648228c2f8d54508235a0dc53091d362aaeae84bca933591c146e2e59819b70829559828b6ae4da5b615a01056edb55b99799b1c20539332f82d06ef58784e6d07743134a7b9727e75450d474182b49b2af4d2565cca8082be7ac48c1b17f519a76f1d13928062af34a9be27ba1d6a4c4ae6b4ac0dec08f11cc55f8e1b81191c301166b2fe73ed6c576d31575b6361e8394f7f0a30faf2e312adadf4789c7b045ed7258bdb0776601c3fea21fada1d154650ed05743e7f08201120c2f96fb131af0954594710cb5b9c7eb3dd0690fac1477ce913df7c2ac36e4a60d0d6cade2634499291d85f2a758bf65c202fb627dfa1f35f40699f3f3ae7be271302aa06461d10dd3690aff17ee62e717c5fd9a7f33ba328465fd107c4a3aae688672ccefb069af98046513956ade8b4e20829819ff502d0665e99a421f8d53782a73901a879996e538e8bd650518bcc2cd1e0b1457ccdb0c4eefca13b3045543e8b67fc9025f05c827537e827959577513fc48be9918e0f9f4595acf3563a97215473d3181353a211762c178efb6a900e782c50b38827a7b34d52f0aa3d2e398232a685899ca4520f7bae1f00471477e6ea2e844871587a5c6003445639dd699d7d30c01237bbde78b820af92e86d60c3de634fd56ed9502b22796cc363b4c113b2f2f2a6823ebd3c097c73e4b2de5f775da5414d22ab7da0a76bd34b5b792237571f94b24c55ae101e68902ab77fefed78bb554c51a3667d9039ff61b708643d32b6e9aa79d601a1daf7a3d5b37ec815ddc6836b08966b4b8d87d3f6d0e48eaa951ba10caebe2eb0cb1c9793b3d3ad0c965fa44fc7e951c34d4018ce82e4b5a317b3a580b4eee2c7637a3d3f38c317249adb497f6c7088c1cffea17f6b871f8c8e3d11ac8a060e7b74d6358cc741b18f19cb0cf5df052f66ceffba1e7e13f4eec0779fd68bf390b91c150f623faaa7d5e4bc6edc86f9a23fe6fdf7dbfd9a8e005b3ed1c046a74ce48263f60e7e576c1ae9a4faeda5d0dfa1ccf8ca7dbaeb9043a10e5aa3c8c86d13923821aeded744785a3201687d151cd1890bebb099e07387c1b4d57195679e081bd8167f34f3ede016a9a72e367931e1e92546de6194f0510f647f374a0c9bb3e5f5b422efdafa51fc233dc7acb49063858888f00f1cd5fbf2f61e71809145fe73add2030644159ff46e5dde146728b47be6e43ca1f82da7d396002d285a67b03588a6503c86fadc5193ddc684f7fc222f627ae4223ba133bb2728a3a93d0f2da29c8b22a2b6c3c97e0a1f496b07c2a451c27aa8fdaaa77b7d73c98a6f2363a8ed2811c597d187684bba9acc41ea9686542a93cd0d27084590b9e455aa4cf1af1198ef73ebdd2f32cd15b37d89f14f67a28e32f6fdd94d91cdaef7d40a90de57eb505ef6397a0944accdcd32dae49eb7543859cf49222014385a902ad497b9cf4a2f0516aa0e229ca836f7f2565a03c268800346615665823e7d3ecb5b40f328c0d8e307287b0f630acfb9c672c323af43a4476658601b782173dcac214ca63a7c022260cd737b3ef050b3b22c787441c1a1c3c82ae27766ee839aee4c80578556204908a2abebe7f0d1cdedbb863bf6e705f8862e15e100fc9e30cf0e4f8f5a16e985b5ad3efb589341107470bef1b781a49fb0bd5b7c5b4b396fb76bed3210ab1ec6e43e479555154d2fedebcab14c9d0b8010a2fc989123fb83c29fff3f6796af8d9c1ea3ad7c647a3271dd1aa797a435c95925b3aa09a5cf46d7dc24896d24fa7cc0747903a215c80e98de08ba4b30bf72b100cac0a1051656dfa2d3d791acdeb08d328ceae4d342fae72f8c914105ad6aa40510418e953f6f48b1e8823e1e4d5193bb6d52370d2baac0832d856123cc7dfcff6e7da5aa294a1ff51944ee3a3732208dd4c31b8008a63f560d8dae0e06a1c78e163fcb35045603039c54f5791c2df849ff3844a88e1af0b3835cb91a9fc55be34d4e9a5271d7eda26709ad6671cdf9f5fa0de9525748750d220e6f16fca88dfb1f0555bbdf28f31885febc85f8554b309bc74e902284229782c6d8ce74b9194a1b0e9e6efe256f8f529ca5d278fba3fe8f2232f9a261b91b7374fec05fadb734bb0b04f1327846c78b827beeda11d041386734d90f62d2884f8295d1866b7e549eff754cf22f28e9406f05a35dd46df3d04da7b1b8774976e208db649a517410818562e0f2535a0f49942d0fced3f73aa2da7b35c687f6cd5d488f9793b33be9d1de2410d6bd349e9197744cb5ff888c8fb307fa162bdd67034876b820957e41bc8bdb5ca49d0bd7ed18f55714de21304f826e6139908d30052e6c0947a056bc02fe18bff11e451b839be02602c3e71803a880abad17e7480a4dcf3656adef880d6520eb7f9a1366a1703b924a5f556fb74fce39c22a74cdef3d186aa38ea64c76937a5cf9ead53ac654c3947635b4571f85b8284aa0571251fd0b3a6883fcf0503ff8ea64700ab27f941190c399160462e210eb0e303bd01f7eea29f1c3dd4b604d84fc73243627e56718d732a9c6cfa89b642dd1b63307410f31787fe91a65ce9e666d5afe5cfedb0e5f1e0467731707120f078ce84840e33fdaba507a7f682fa3d6669fd668ac0571e532582a4dd29778ce0c31012ef749f3764a60479d46a8c913575ca737d4d541237aa39736b76a81723957b6be87c682e021faf0e8ba33333bd00893bfc3118c4785d7871abf5eac490fc01834dea1bb9146efadc4815b86fbf358038643b269afaed4294ed7dbbe2b47c1d669dc3af99439188d115fccee7f585d4b9c3b41c39ddb01405c5b17de27d2d00d8092a54fcac65360d84f52cc1b2b9fb246eb231aa0e06e45224dec2184f86c6ef9ebb94409618a504299c5e4fc6c3760299c6d7f07533ad1fb22da2fcaaf2b40506c063e0be29432b80b0758d1a03af33e1158b0b5df7583fa2facaa3094a700feff30c5b13d692e779a181bb05b8902a6020187b526d36356aaf9f2835810db587255f9b8a9442862dba873d3c8bcaf546253653d888577c75d8965f2c576a7f8754294e5cf458d3ace97b976ccc29fec5863e171153353d26364a9f10f5da18977e24985ad1231d61cf4f3ca1b15355f28dce005be928a2dd21f4d6fc0d8b71c26830e59f16927889be99c6fd78b72d9e7a8c0cf7fcb4f098a80bf1433b9875cc5cfe60a5a86e763bbb0f501e7c24070c90d196129105cc17a0d870291fcbffd9db6a028787beb5be2425ea819764c9906a444c097cde65939d6341d174bf493d6c98893c51fefb1f4b180366544dd8936f61abf7203520bb0dc2551c6cd935932402fa1413c9893392be23a0383d56b5e6b5e14fcdf95f8712afa4f995afd9c9702c7125b48dbfc35a036ff6297488d7f588b1353fbabec3bd2fcd449fec1fed66c53391172db8f642c8ae14fbe90b2795ff650cca5df0c278d1416d576850663ad4c836099f4d9dd4327fb48daeb958366572b886eb0bdb1db66f826dea7750b1d6947cc91900cefdf1ce308874e0fc8f3eb1d21f867e4100b025217487d1aa51b97e23caa41ca0cdde05df8128dd990404efbac0bf54e36ded9378e27de624a70b3ad711237e106641a80ad4394c5b68d497dc5fcfb9ca7cf868f6396a542d57524566bb967c759dc7aaea6e076b97e78b2e70e6186e305fad825a9ca1a42fd84fda502e7089495d300c8903b7eade093dba09d1706839f69e7c37c40f143c8990c29940ec3862f122606c621d113d33f34769f6934bd8b5c96ba19848937fa343647bfab5a51a8c92f6c5b5ca8f548c22bfda729e0bb8d8a53b99f23b5a9abaaaa3e8f41824e33e5b8fecf9fc1331300de2627100f66340ac330c210b44f773ad98a481a205fa2eb3e4e5aee1ee1fa1aa17688bf648f8131b18d42b7cfdbee75e76a03cf476be83f094907333f46a60eabb3b7f32d51f40044d513558b7b0c6a77421c0024fa161abc64239d308d97b183782bc50f6e90d22841b66035ac8ec448a4f3c2bbeb475296000b1443585d61717987a5295168d2f33659789e8485a3fb868d144f66868f90bdcbd7020e1b2b383e4b5c6f88ddea0710383b467bb9bcdeeb0000000000000000000000000000000000000b1014181a232f39", - "result": "invalid", - "flags": [ - "InvalidContext" - ] - }, - { - "tcId": 6, - "comment": "short signature", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a1115182027", - "result": "invalid", - "flags": [ - "IncorrectSignatureLength" - ] - }, - { - "tcId": 7, - "comment": "long signature", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a11151820273100", - "result": "invalid", - "flags": [ - "IncorrectSignatureLength" - ] - }, - { - "tcId": 8, - "comment": "signature with a bit flip in c_tilde", - "msg": "48656c6c6f20776f726c64", - "sig": "bb4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 9, - "comment": "signature with a bit flip in z[0]", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906959d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 10, - "comment": "signature with a bit flip in z[1]", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e61c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 11, - "comment": "signature with a bit flip in z[2]", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbf8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 12, - "comment": "signature with a bit flip in z[3]", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a741a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 13, - "comment": "signature with a bit flip in z[4]", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314d2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 14, - "comment": "signature with a bit flip in z[5]", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7230856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 15, - "comment": "signature with a bit flip in z[6]", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6381c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 16, - "comment": "signature with a bit flip in hints", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052e3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 17, - "comment": "signature with a bit flip in the last byte", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202730", - "result": "invalid", - "flags": [ - "ModifiedSignature" - ] - }, - { - "tcId": 18, - "comment": "signature with hints in reverse order", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "8243e3f28052056de7cc4b042fe1d959767644a1b000c5fc3cab98cd8d86670c2025a62784c13c5eb0f71b9546dae058ec5027d4e6ef29dd36e8ac6ba1dbea78cd5126919dec30e8bf50e9034aa5582d522bb97d30a7dbfb1af52d9cb655b7561a17a9df3d09b277849b0f4106cec822d715bc4dacea258f60f4b9adea3b394627b318d2f305dd612fa0826791b03c0a55f456ac9b8ddcbc67c88b6e07375e3aa5114a95afdc98e1167e7cb1c74bce4c835d1b47cd1be95356cf6abc3c9b36dcd2ce4b0267a1e0afc0cc9b7e3d0df7111efe0f936c79bb2ec2b3e65b0641373ba1096bd1006f19e0fda9c7d8082f5e09ae1673cbae86caf98cfe853a2edd27c48fffba468dd6808b0996cdc5eb50f7847f80e51f353ae9afc4a0008248901c25b5328dcae28617d3dcc9556f3e1bd86000e1630210bc8a6ca56d4f0bd61ec09b0ed6d4961cb56ff253039bc8f3b4f9e406ce7e408e8861e599ad05e238d214fface8605e3a3e2173d4b5e1456edced533cacf7135e0d212c4934982072a924074dd6ff9eb3985eaa4e108799c5609b936e2a0dcb32369ccf34766462dd2e310e561fbb09800719bdea3eff789b64b3602c2303286499cbf45cc769d8e955c2a0bc87e6dd60a94284fea121540966d1a8cb893695279771a12eb8b05e33cfe1ce5566337bf90dd241d9c31fb07c6205940b77f158a7250c5698d6c5c251e787bc81338f2171bbdeb3dfb29b2e9202c29365f33e18fe927ef0919482260c01b2fc94c90222ba4dcb14723dfbb3d6fce66da6eb6013bc455848e5c2e3f52f1bddc5596d4a5f18c8f9085b3f25b4d95f8497b818808e5628f94f03b4d838c013a3c2bae7498ed2f23449d77ce94069d2d1c50d12df6d8fb8c8f72b03bf04a3df67ce2990b56595fec781ecbedced215fc0d0b5e34c10819c242a122a4deeb607fb9d3dc68ead4ee07726082d132beb524ce9937b66ef218c221d77cee77ce255b5f18e7cd7c3e2ef9afe80c7bb6675128c90cf6b483d96bc6156f2b7a4d4c98097d2b3086519cacdc3bf35f8127cdd071136b889f1111c0db2953d4d47f8a9de23df6372d65e25b4f8887b4553ad11de8ffe01264ee810a5caac6cb214baf3ec4e5062bdeb0f892014e3551e1e8f5fa50defd5bbc7ec14839b1660d2b5afa5d67a945989f934205902b3c8d62a2190621c6fd3f47be0a69f68b61a5ed1b2c4ff03c7c22fb67a621a64889b1bdf1c27ca1c7322e6233d433cf9bf0ef2c3877bc9780fea6b1a7cc15af6d370e57ef36ddd0a612f1f7e25efdc7762c70c9cd925e545672ec8acdc77872745c7fee82c572d34c9341ba176a2f1e4e629bd1342d00d8bdbc12eaf17e3c2399057ff2a6ebc7834cc80f3ead92b86e0c9cd0a909eb074d97e7783074374454eeeee970e8aa7fe4c27eccc340adb62fc838fd23554554e62c0e4ee0a50a1f2cba806b6172dfca4e3943d4af28fc4e6beb054487d47f26d0d56b8c0f70393eba137c5f3c278438d264d35ff2225f4b8400ee97e550d7770637745cb7ca1cca4825cdcb9c9eedea9bccb9e7c9c2f43e5b95892422514890c465a4784ac10dfd3c3c5ecaeb4f74d7c7c1f41b2ef8a6e27879ce049054a3947e2f71a36c11f439af849bedddd2d4e23fa71857aaf34d8a082d034b3e6a438bd195e07c9d9a0d66a10a7c6a93bd9346314d8ba8ad5b2df800db47d38266b5052d82f7585ff57c9a4ab2f5c09f95b2e050b57e3135fc1b3832d86bde221baf6996c9a95e50984c7a2776a948f4ec98a21ee77507932e8da0fa1baaeeee4ccf34ee03f62bf3c267b3e02c327ec57c17e4cb2ef1be78e22c4090ec356c0c9d2b729b44e5d74d1583aa73de3d2187c910c5f30cb41586c014e1e44fa91c6155c646ead2f60e42017156326d8a4258addc65dc2fcf63d80c9d504d77222ce363b313bf396cffd8cfb802bf6c2f99e5e440fdbb374900b569a31f04e2ccbcaa29985e60c980b75dc8167e6526825005b07ee9dfe7df419ca5660315a5ddd47d70aa0a47e9e914f0160fccf4980a77a36fb78f02530dc01a88fc2e2be50d20f6066410671ad48bb65f4eee60b296abe47aa86967e454a4892c46d1b125fbf121c2972575de626b5b3320b419a58c844f6d0e4b4aa7308cffd4240aa4180f97b1241ff641d09c90bb40d4d4071f85b913a1a35421aac0be77db6c53e964537ca6ffd8795f21345b62d37a50a6544420f7142d54e6440864a0726172937974a12d775f69037266f501a9120fa31f71dbb64d562e11749260d4d3b3ddec8049199e0c34593dc34b7f5f51cdb963205ff57250d7bed8856deebceb18e8bec50dc74e9b3bfa359f43fdca881c9412fe5c791a7b0e0313300d6bd0b9b7177efffebb7aab23af990ca0fdea4957c2412ea51a7b72efc6be1aba08ed7bba5097be312b4cd3e684e47ef0aa96a5bc18da275bb9ef77f9ba05f4eb5fe1d8b88bfb7a8edfee8705dbe213005052d6c137ac399fb29c5c146bfb371a1f994f0b0563e5aa443167321318bb002434a79b2705aa24cfc36f7f748128bf7e38041a64cdc5459f2446ba34ce73959fe504587b5f5c2f91d2b5b9ded36724cf7f375cebc67dc5f3c5eb37a9d6095250c82d414544726e22392e9a7859898aacfdf18d2361f55139d32dd4786634ea2f59b0ea8db2f03ec335a3d8add4491c3377e3d5113b59e79360d816ec53834c8994ef04f634368d3d135aecaa1d54da5b63b606dac31c5969007e501360e60559e6f01c25a608724b13b978835b4cfcb69ca2deeb2d8b6235ebce9b0123ffad14c4cba462e47c54f7a5a93c5c8e1abe257e21ead4a6216a06aa454a15f8780c1632895dc497062048f04085e360918eaf7d800d4dc7b9907adb5a1efd1a982375792ea5c27d73bfb9f837dec8077cdbdcbadf95b02aacb8b88a725df65743db5a59348bbce2bd46a80bc9485aba23500f03890e8d114153bfd037a87d1ae27a7576d86bf435373d021c85a2a31cb1d978127f89fdcb7ecad2fef36de77ce19307e4ef1ad6fbf2c23224613868c184b318b77430c5e783ed0745c9b76e635fc808cbb62652baef12c848730893b7c6c3c713711f6d7819c8bbd126be7c743e66dfeef86b13ee6d74735edd1884badfa8dcad7107d86f841f69aeea05b28d75670696ee81fc34fa3a822b31a945141c56ae5154a56a04353e6a3c120d47ca11144d460005c75789e5251a225155d3655f6566dbbe26e248532ee4b5345c97b9eadb6f4bf629eca64d269eec8487efb7f7557052490d8fa144f5c0deadef6549cf5c167a02f208f2889d8cf9f380cea5960394ab163cad4b7a56dfdbc67be3f0e915ab030bc5018ac5f5a636b219aa00c077a22437d975689cee84b2b2555a3d5ff145ddf2a0e27b724265cd60c4db153e9975cd8ac5bb5658e5f61cddd821c31c349f770536be773ddf11b42d44fc22d5f954617b49a74e998459f230498e428927e875afe309779aca4bdab38eeb03fb8345b58ffac10a7b1e862e1fc9eb44def447a1e89ad707d36cd9d74f5f38a36251bdef3adc807ac384976b7c82133ff8d0ad5041116c428a45c9447934945def2f008aeac3477cafe3508392bcb5fd3db35a589f38c1b944e079aefbfadccc22061227936566c1b662c62d3816324582058dab11512eb1d6bbafac7cf7bbc4ff88801431ba5b14146fe27456e67fa285b81ebd34cf82fea2977dc70979b82f03d7e17815cf783b54e6e5096609653181c94dc8183c8b5561a8f8a3790f22c261ef3dcb7eb8c7a3eb0f432f016c92e0ee5084d121cfdd34b214bf7715de4dd6bba38d05a90806787cda65aa739d41d9511d7e0bdd9b6395f8b205be597590980a17f631d877a801c469f2e81fe6a44b915d89b04a3b35f087517be09cc2460af73d34b9c898ebe8dc48176316b3b747e1a8d6e0fd7d19753ca03b5c3ef1d0d9122e7c5fd373bbabec86da39fc3a223d3de048b2519fbd892634821dc195c011c078eddacde76fcc1a728906214e12be5901da2739751c2a5aed665b10a55b265e80c75e6d11e1d8ba9ae2e27fced1234b11ec8296eaafc0cbce4d65f1750a6fd82cd3fce774d66249d0d4e21272330cfbe89ab722ee78ea6ccc3113f6829e7d437b307b6eb0cec0082511ef8c69492ed46752523d5e4bbef2799eb76940f4035c101833f7059fa4c9c7765aa0d378c96982e47285aad8a2c5dc33303e2063166c10a8158f5e9e0b86fe152035d767be0dec7b4fc97313bd50c27bbd2323aee3d8b508a2fe395024cd8331996fed16f97ebf70ecbe997de5b8bb888ae8e522360097eed1c96fb2ad50af4a2a8961be88b46aecbcf31c573d5f172074f20e98d68be6129a1360a7c8dbc0dd74a21d936deb873d33e66f8d8f6ba73d8a05a473272b249025a8ad5740f7f37aa5661efe6558138d8487644ffc05f952777083ee67d180b80b1128a3a1b93dd3aee189f9eea635a49da7adfa127b7e2e5567e3e0d58efb6ae588d336bf38121e6f5494e66bc1a9e1f975d596468563f2af990bf08ec933016e9c50f086904f30ec130bf4a735d7b414d1726aa03222ccddef29b4ee69062e217928a00eb0dab678ecacd601ef33d6482e39bfcb04325289f7316d38938460e023ed12f38c38e08fdf6c75341909902408a5fe8786c25716683661f0060222db5d9a1188e9624d6eff0bbd3164adc28d6e09b339c0d825a6653503bf7251972f208cfdc0bdd1557f2f9892f3db0a9efc8409bf6c83b2e31bad172cb2dd95ae311d873bb80e642342814bb71890b5ac9e116f0f367bc85a790839e8dc1dd52b167f6abb3809ef2e8a34f6dde611aa4f75409f6c9e0bef4353d1c2c50df590130365e20204ffe392ee3438d644b8eea3f4a92c3184e232745957ffb88326b7846d4a64eda2cdd5b95412235e6420de10158930f675900f9b558867afbe6c182e37cbeb3625d88adf0dec9c8a3a096dca43b3c7e9eaa54384f4f987354407f2855f4ee5746ffcac55293d9187a668ec72c12468f588b7088b069b20aa03cd1ff3bd9af26e922922e327ba6a424eb0aa9180cb60da4c45a6b76aea03258818d9010ffb6ed4fd0e4453188513a15382e4e057708f4ef24d57d00968009c1022f3a40acca9dfa5523d7fd3e63603f198a5c72855e1b6169a333925fa5c4325efab41ca4800149dfdc8ce7635836978f797bdebf875294128f3ad72ed91ca8b52476f4c7e0c67082113d2dc327a4f6deee33bda8a7db96672b990614edcc7138cea1a006867ff22528f8eb7602720c58564cc8a9cff02b404355a03d60f03fa07cc74a6ba70dc4aa8f2122e5b7863af835ce5fa0e80ce1e62534615a240aadaf1e09f8d201559e19879f6f7715cc459229784bd67a3db8e6d65cf4b149b678a89661b3d0a2f22709347e28ba2bc4d4c408c7df1861266ae1fe47a32c22eea95164a42fdd9070e4403f5a8cf39bcff30f97b7dbbe54cfe09f1dde66f84be59754555e64af1d52508e59b97110440ae59da8cb70f2e7c551d3e41b281b80bead47668dcf8e7f1b2abc09af9af89f51c8690ac965aa2ef6ef565a532c7a0aba5520c41c1d365326a5d5e6f1b6796ccc828290e18a502c2fd403d915f96e01cf1936703ef01a781d7f48efde73d99e80f551768f1cab025f176cda4c9222a074426af4f94547b5108b89534344424f1985558111b570ca48955ed1035af01a507e93abb177447f778461a5908e5e1040b9ebae6d1d2f303cfb463d9784cffc3a95c6631b318ccd952ae9915c6de13374446cad492f84ecc36a4a95d520a76ada6a5437ee4719e73cf997b5a3a590a68356419888ddee7ba6db7288c36d5aef6030123bbf029f8ecb8302155d4160ff4c4c82cbc3f97b463791bbdd561431ca1fec380b31b5fcbdc920e634bd2b42eb8826d96b605a69c60c92a51359ab687b90b78ae6d94e51b64d721844b8b73a71fd1f201c41f2871e3a6e5d0b0e0050437938dc298f241974ae1c00e90e72e04c6ca294416c2ea243174076463b027addf5c423a93bbffa08893f9d401dd970ab0a907ecadde16a41bc95d492dfb8ad2d7ba7f96a98c30afe47011501608df033bf1d49b1b5135542ae8b0f6e556e0e49a9883e4632c6da8f6f4734e2754736280e0979faa883c5815033896644361363045923b8774b8aae0241f2ece112daf259ce072a1fb2c236913a52a9c2a9ad0b2e3a74a3c612a654f313b230673161bd54f9c0c907652a4a1e13677661fead894b893f8245525e6e39d43e5cef2f5686b07c94dfddf62d35f9c256df6c71ed2e4aed383cc6841b3ed6de8019ba6464c6db9c7c7156fe67b899745a65f0fe624b25a2763b7453233d522fd3a2073309ad4228452b84367d229831c86156df0e04aac208b9433c46d8fd03f252453505295ea12278724d473e261c1b05edcdbcad15e3ce847c6f1f04dd9241dbd7cf816f52332e250efff6beb7b3976452282708d4c6917f59422af0dcb9a89a81775b410900000000000000000000000000090e1518222d343e", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 19, - "comment": "signature with too many hints (causing a buffer overflow)", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "8243e3f28052056de7cc4b042fe1d959767644a1b000c5fc3cab98cd8d86670c2025a62784c13c5eb0f71b9546dae058ec5027d4e6ef29dd36e8ac6ba1dbea78cd5126919dec30e8bf50e9034aa5582d522bb97d30a7dbfb1af52d9cb655b7561a17a9df3d09b277849b0f4106cec822d715bc4dacea258f60f4b9adea3b394627b318d2f305dd612fa0826791b03c0a55f456ac9b8ddcbc67c88b6e07375e3aa5114a95afdc98e1167e7cb1c74bce4c835d1b47cd1be95356cf6abc3c9b36dcd2ce4b0267a1e0afc0cc9b7e3d0df7111efe0f936c79bb2ec2b3e65b0641373ba1096bd1006f19e0fda9c7d8082f5e09ae1673cbae86caf98cfe853a2edd27c48fffba468dd6808b0996cdc5eb50f7847f80e51f353ae9afc4a0008248901c25b5328dcae28617d3dcc9556f3e1bd86000e1630210bc8a6ca56d4f0bd61ec09b0ed6d4961cb56ff253039bc8f3b4f9e406ce7e408e8861e599ad05e238d214fface8605e3a3e2173d4b5e1456edced533cacf7135e0d212c4934982072a924074dd6ff9eb3985eaa4e108799c5609b936e2a0dcb32369ccf34766462dd2e310e561fbb09800719bdea3eff789b64b3602c2303286499cbf45cc769d8e955c2a0bc87e6dd60a94284fea121540966d1a8cb893695279771a12eb8b05e33cfe1ce5566337bf90dd241d9c31fb07c6205940b77f158a7250c5698d6c5c251e787bc81338f2171bbdeb3dfb29b2e9202c29365f33e18fe927ef0919482260c01b2fc94c90222ba4dcb14723dfbb3d6fce66da6eb6013bc455848e5c2e3f52f1bddc5596d4a5f18c8f9085b3f25b4d95f8497b818808e5628f94f03b4d838c013a3c2bae7498ed2f23449d77ce94069d2d1c50d12df6d8fb8c8f72b03bf04a3df67ce2990b56595fec781ecbedced215fc0d0b5e34c10819c242a122a4deeb607fb9d3dc68ead4ee07726082d132beb524ce9937b66ef218c221d77cee77ce255b5f18e7cd7c3e2ef9afe80c7bb6675128c90cf6b483d96bc6156f2b7a4d4c98097d2b3086519cacdc3bf35f8127cdd071136b889f1111c0db2953d4d47f8a9de23df6372d65e25b4f8887b4553ad11de8ffe01264ee810a5caac6cb214baf3ec4e5062bdeb0f892014e3551e1e8f5fa50defd5bbc7ec14839b1660d2b5afa5d67a945989f934205902b3c8d62a2190621c6fd3f47be0a69f68b61a5ed1b2c4ff03c7c22fb67a621a64889b1bdf1c27ca1c7322e6233d433cf9bf0ef2c3877bc9780fea6b1a7cc15af6d370e57ef36ddd0a612f1f7e25efdc7762c70c9cd925e545672ec8acdc77872745c7fee82c572d34c9341ba176a2f1e4e629bd1342d00d8bdbc12eaf17e3c2399057ff2a6ebc7834cc80f3ead92b86e0c9cd0a909eb074d97e7783074374454eeeee970e8aa7fe4c27eccc340adb62fc838fd23554554e62c0e4ee0a50a1f2cba806b6172dfca4e3943d4af28fc4e6beb054487d47f26d0d56b8c0f70393eba137c5f3c278438d264d35ff2225f4b8400ee97e550d7770637745cb7ca1cca4825cdcb9c9eedea9bccb9e7c9c2f43e5b95892422514890c465a4784ac10dfd3c3c5ecaeb4f74d7c7c1f41b2ef8a6e27879ce049054a3947e2f71a36c11f439af849bedddd2d4e23fa71857aaf34d8a082d034b3e6a438bd195e07c9d9a0d66a10a7c6a93bd9346314d8ba8ad5b2df800db47d38266b5052d82f7585ff57c9a4ab2f5c09f95b2e050b57e3135fc1b3832d86bde221baf6996c9a95e50984c7a2776a948f4ec98a21ee77507932e8da0fa1baaeeee4ccf34ee03f62bf3c267b3e02c327ec57c17e4cb2ef1be78e22c4090ec356c0c9d2b729b44e5d74d1583aa73de3d2187c910c5f30cb41586c014e1e44fa91c6155c646ead2f60e42017156326d8a4258addc65dc2fcf63d80c9d504d77222ce363b313bf396cffd8cfb802bf6c2f99e5e440fdbb374900b569a31f04e2ccbcaa29985e60c980b75dc8167e6526825005b07ee9dfe7df419ca5660315a5ddd47d70aa0a47e9e914f0160fccf4980a77a36fb78f02530dc01a88fc2e2be50d20f6066410671ad48bb65f4eee60b296abe47aa86967e454a4892c46d1b125fbf121c2972575de626b5b3320b419a58c844f6d0e4b4aa7308cffd4240aa4180f97b1241ff641d09c90bb40d4d4071f85b913a1a35421aac0be77db6c53e964537ca6ffd8795f21345b62d37a50a6544420f7142d54e6440864a0726172937974a12d775f69037266f501a9120fa31f71dbb64d562e11749260d4d3b3ddec8049199e0c34593dc34b7f5f51cdb963205ff57250d7bed8856deebceb18e8bec50dc74e9b3bfa359f43fdca881c9412fe5c791a7b0e0313300d6bd0b9b7177efffebb7aab23af990ca0fdea4957c2412ea51a7b72efc6be1aba08ed7bba5097be312b4cd3e684e47ef0aa96a5bc18da275bb9ef77f9ba05f4eb5fe1d8b88bfb7a8edfee8705dbe213005052d6c137ac399fb29c5c146bfb371a1f994f0b0563e5aa443167321318bb002434a79b2705aa24cfc36f7f748128bf7e38041a64cdc5459f2446ba34ce73959fe504587b5f5c2f91d2b5b9ded36724cf7f375cebc67dc5f3c5eb37a9d6095250c82d414544726e22392e9a7859898aacfdf18d2361f55139d32dd4786634ea2f59b0ea8db2f03ec335a3d8add4491c3377e3d5113b59e79360d816ec53834c8994ef04f634368d3d135aecaa1d54da5b63b606dac31c5969007e501360e60559e6f01c25a608724b13b978835b4cfcb69ca2deeb2d8b6235ebce9b0123ffad14c4cba462e47c54f7a5a93c5c8e1abe257e21ead4a6216a06aa454a15f8780c1632895dc497062048f04085e360918eaf7d800d4dc7b9907adb5a1efd1a982375792ea5c27d73bfb9f837dec8077cdbdcbadf95b02aacb8b88a725df65743db5a59348bbce2bd46a80bc9485aba23500f03890e8d114153bfd037a87d1ae27a7576d86bf435373d021c85a2a31cb1d978127f89fdcb7ecad2fef36de77ce19307e4ef1ad6fbf2c23224613868c184b318b77430c5e783ed0745c9b76e635fc808cbb62652baef12c848730893b7c6c3c713711f6d7819c8bbd126be7c743e66dfeef86b13ee6d74735edd1884badfa8dcad7107d86f841f69aeea05b28d75670696ee81fc34fa3a822b31a945141c56ae5154a56a04353e6a3c120d47ca11144d460005c75789e5251a225155d3655f6566dbbe26e248532ee4b5345c97b9eadb6f4bf629eca64d269eec8487efb7f7557052490d8fa144f5c0deadef6549cf5c167a02f208f2889d8cf9f380cea5960394ab163cad4b7a56dfdbc67be3f0e915ab030bc5018ac5f5a636b219aa00c077a22437d975689cee84b2b2555a3d5ff145ddf2a0e27b724265cd60c4db153e9975cd8ac5bb5658e5f61cddd821c31c349f770536be773ddf11b42d44fc22d5f954617b49a74e998459f230498e428927e875afe309779aca4bdab38eeb03fb8345b58ffac10a7b1e862e1fc9eb44def447a1e89ad707d36cd9d74f5f38a36251bdef3adc807ac384976b7c82133ff8d0ad5041116c428a45c9447934945def2f008aeac3477cafe3508392bcb5fd3db35a589f38c1b944e079aefbfadccc22061227936566c1b662c62d3816324582058dab11512eb1d6bbafac7cf7bbc4ff88801431ba5b14146fe27456e67fa285b81ebd34cf82fea2977dc70979b82f03d7e17815cf783b54e6e5096609653181c94dc8183c8b5561a8f8a3790f22c261ef3dcb7eb8c7a3eb0f432f016c92e0ee5084d121cfdd34b214bf7715de4dd6bba38d05a90806787cda65aa739d41d9511d7e0bdd9b6395f8b205be597590980a17f631d877a801c469f2e81fe6a44b915d89b04a3b35f087517be09cc2460af73d34b9c898ebe8dc48176316b3b747e1a8d6e0fd7d19753ca03b5c3ef1d0d9122e7c5fd373bbabec86da39fc3a223d3de048b2519fbd892634821dc195c011c078eddacde76fcc1a728906214e12be5901da2739751c2a5aed665b10a55b265e80c75e6d11e1d8ba9ae2e27fced1234b11ec8296eaafc0cbce4d65f1750a6fd82cd3fce774d66249d0d4e21272330cfbe89ab722ee78ea6ccc3113f6829e7d437b307b6eb0cec0082511ef8c69492ed46752523d5e4bbef2799eb76940f4035c101833f7059fa4c9c7765aa0d378c96982e47285aad8a2c5dc33303e2063166c10a8158f5e9e0b86fe152035d767be0dec7b4fc97313bd50c27bbd2323aee3d8b508a2fe395024cd8331996fed16f97ebf70ecbe997de5b8bb888ae8e522360097eed1c96fb2ad50af4a2a8961be88b46aecbcf31c573d5f172074f20e98d68be6129a1360a7c8dbc0dd74a21d936deb873d33e66f8d8f6ba73d8a05a473272b249025a8ad5740f7f37aa5661efe6558138d8487644ffc05f952777083ee67d180b80b1128a3a1b93dd3aee189f9eea635a49da7adfa127b7e2e5567e3e0d58efb6ae588d336bf38121e6f5494e66bc1a9e1f975d596468563f2af990bf08ec933016e9c50f086904f30ec130bf4a735d7b414d1726aa03222ccddef29b4ee69062e217928a00eb0dab678ecacd601ef33d6482e39bfcb04325289f7316d38938460e023ed12f38c38e08fdf6c75341909902408a5fe8786c25716683661f0060222db5d9a1188e9624d6eff0bbd3164adc28d6e09b339c0d825a6653503bf7251972f208cfdc0bdd1557f2f9892f3db0a9efc8409bf6c83b2e31bad172cb2dd95ae311d873bb80e642342814bb71890b5ac9e116f0f367bc85a790839e8dc1dd52b167f6abb3809ef2e8a34f6dde611aa4f75409f6c9e0bef4353d1c2c50df590130365e20204ffe392ee3438d644b8eea3f4a92c3184e232745957ffb88326b7846d4a64eda2cdd5b95412235e6420de10158930f675900f9b558867afbe6c182e37cbeb3625d88adf0dec9c8a3a096dca43b3c7e9eaa54384f4f987354407f2855f4ee5746ffcac55293d9187a668ec72c12468f588b7088b069b20aa03cd1ff3bd9af26e922922e327ba6a424eb0aa9180cb60da4c45a6b76aea03258818d9010ffb6ed4fd0e4453188513a15382e4e057708f4ef24d57d00968009c1022f3a40acca9dfa5523d7fd3e63603f198a5c72855e1b6169a333925fa5c4325efab41ca4800149dfdc8ce7635836978f797bdebf875294128f3ad72ed91ca8b52476f4c7e0c67082113d2dc327a4f6deee33bda8a7db96672b990614edcc7138cea1a006867ff22528f8eb7602720c58564cc8a9cff02b404355a03d60f03fa07cc74a6ba70dc4aa8f2122e5b7863af835ce5fa0e80ce1e62534615a240aadaf1e09f8d201559e19879f6f7715cc459229784bd67a3db8e6d65cf4b149b678a89661b3d0a2f22709347e28ba2bc4d4c408c7df1861266ae1fe47a32c22eea95164a42fdd9070e4403f5a8cf39bcff30f97b7dbbe54cfe09f1dde66f84be59754555e64af1d52508e59b97110440ae59da8cb70f2e7c551d3e41b281b80bead47668dcf8e7f1b2abc09af9af89f51c8690ac965aa2ef6ef565a532c7a0aba5520c41c1d365326a5d5e6f1b6796ccc828290e18a502c2fd403d915f96e01cf1936703ef01a781d7f48efde73d99e80f551768f1cab025f176cda4c9222a074426af4f94547b5108b89534344424f1985558111b570ca48955ed1035af01a507e93abb177447f778461a5908e5e1040b9ebae6d1d2f303cfb463d9784cffc3a95c6631b318ccd952ae9915c6de13374446cad492f84ecc36a4a95d520a76ada6a5437ee4719e73cf997b5a3a590a68356419888ddee7ba6db7288c36d5aef6030123bbf029f8ecb8302155d4160ff4c4c82cbc3f97b463791bbdd561431ca1fec380b31b5fcbdc920e634bd2b42eb8826d96b605a69c60c92a51359ab687b90b78ae6d94e51b64d721844b8b73a71fd1f201c41f2871e3a6e5d0b0e0050437938dc298f241974ae1c00e90e72e04c6ca294416c2ea243174076463b027addf5c423a93bbffa08893f9d401dd970ab0a907ecadde16a41bc95d492dfb8ad2d7ba7f96a98c30afe47011501608df033bf1d49b1b5135542ae8b0f6e556e0e49a9883e4632c6da8f6f4734e2754736280e0979faa883c5815033896644361363045923b8774b8aae0241f2ece112daf259ce072a1fb2c236913a52a9c2a9ad0b2e3a74a3c612a654f313b230673161bd54f9c0c907652a4a1e13677661fead894b893f8245525e6e39d43e5cef2f5686b07c94dfddf62d35f9c256df6c71ed2e4aed383cc6841b3ed6de8019ba6464c6db9c7c7156fe67b899745a65f0fe624b25a2763b7453233d522fd3a2073309ad4228452b84367d229831c86156df0e04aac208b9433c46d8fd03f252453505295ea122051b1c263e474d727815adbccded041f6f7c84cee34192dd0e252e33526f81cfd7db082728526497b3b7bef6ff2a42597f91c6d409415b77819aa8b9dcf000000000000000000000000000090e1518222d34ff", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 20, - "comment": "signature with non-zero padding in hints", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "8243e3f28052056de7cc4b042fe1d959767644a1b000c5fc3cab98cd8d86670c2025a62784c13c5eb0f71b9546dae058ec5027d4e6ef29dd36e8ac6ba1dbea78cd5126919dec30e8bf50e9034aa5582d522bb97d30a7dbfb1af52d9cb655b7561a17a9df3d09b277849b0f4106cec822d715bc4dacea258f60f4b9adea3b394627b318d2f305dd612fa0826791b03c0a55f456ac9b8ddcbc67c88b6e07375e3aa5114a95afdc98e1167e7cb1c74bce4c835d1b47cd1be95356cf6abc3c9b36dcd2ce4b0267a1e0afc0cc9b7e3d0df7111efe0f936c79bb2ec2b3e65b0641373ba1096bd1006f19e0fda9c7d8082f5e09ae1673cbae86caf98cfe853a2edd27c48fffba468dd6808b0996cdc5eb50f7847f80e51f353ae9afc4a0008248901c25b5328dcae28617d3dcc9556f3e1bd86000e1630210bc8a6ca56d4f0bd61ec09b0ed6d4961cb56ff253039bc8f3b4f9e406ce7e408e8861e599ad05e238d214fface8605e3a3e2173d4b5e1456edced533cacf7135e0d212c4934982072a924074dd6ff9eb3985eaa4e108799c5609b936e2a0dcb32369ccf34766462dd2e310e561fbb09800719bdea3eff789b64b3602c2303286499cbf45cc769d8e955c2a0bc87e6dd60a94284fea121540966d1a8cb893695279771a12eb8b05e33cfe1ce5566337bf90dd241d9c31fb07c6205940b77f158a7250c5698d6c5c251e787bc81338f2171bbdeb3dfb29b2e9202c29365f33e18fe927ef0919482260c01b2fc94c90222ba4dcb14723dfbb3d6fce66da6eb6013bc455848e5c2e3f52f1bddc5596d4a5f18c8f9085b3f25b4d95f8497b818808e5628f94f03b4d838c013a3c2bae7498ed2f23449d77ce94069d2d1c50d12df6d8fb8c8f72b03bf04a3df67ce2990b56595fec781ecbedced215fc0d0b5e34c10819c242a122a4deeb607fb9d3dc68ead4ee07726082d132beb524ce9937b66ef218c221d77cee77ce255b5f18e7cd7c3e2ef9afe80c7bb6675128c90cf6b483d96bc6156f2b7a4d4c98097d2b3086519cacdc3bf35f8127cdd071136b889f1111c0db2953d4d47f8a9de23df6372d65e25b4f8887b4553ad11de8ffe01264ee810a5caac6cb214baf3ec4e5062bdeb0f892014e3551e1e8f5fa50defd5bbc7ec14839b1660d2b5afa5d67a945989f934205902b3c8d62a2190621c6fd3f47be0a69f68b61a5ed1b2c4ff03c7c22fb67a621a64889b1bdf1c27ca1c7322e6233d433cf9bf0ef2c3877bc9780fea6b1a7cc15af6d370e57ef36ddd0a612f1f7e25efdc7762c70c9cd925e545672ec8acdc77872745c7fee82c572d34c9341ba176a2f1e4e629bd1342d00d8bdbc12eaf17e3c2399057ff2a6ebc7834cc80f3ead92b86e0c9cd0a909eb074d97e7783074374454eeeee970e8aa7fe4c27eccc340adb62fc838fd23554554e62c0e4ee0a50a1f2cba806b6172dfca4e3943d4af28fc4e6beb054487d47f26d0d56b8c0f70393eba137c5f3c278438d264d35ff2225f4b8400ee97e550d7770637745cb7ca1cca4825cdcb9c9eedea9bccb9e7c9c2f43e5b95892422514890c465a4784ac10dfd3c3c5ecaeb4f74d7c7c1f41b2ef8a6e27879ce049054a3947e2f71a36c11f439af849bedddd2d4e23fa71857aaf34d8a082d034b3e6a438bd195e07c9d9a0d66a10a7c6a93bd9346314d8ba8ad5b2df800db47d38266b5052d82f7585ff57c9a4ab2f5c09f95b2e050b57e3135fc1b3832d86bde221baf6996c9a95e50984c7a2776a948f4ec98a21ee77507932e8da0fa1baaeeee4ccf34ee03f62bf3c267b3e02c327ec57c17e4cb2ef1be78e22c4090ec356c0c9d2b729b44e5d74d1583aa73de3d2187c910c5f30cb41586c014e1e44fa91c6155c646ead2f60e42017156326d8a4258addc65dc2fcf63d80c9d504d77222ce363b313bf396cffd8cfb802bf6c2f99e5e440fdbb374900b569a31f04e2ccbcaa29985e60c980b75dc8167e6526825005b07ee9dfe7df419ca5660315a5ddd47d70aa0a47e9e914f0160fccf4980a77a36fb78f02530dc01a88fc2e2be50d20f6066410671ad48bb65f4eee60b296abe47aa86967e454a4892c46d1b125fbf121c2972575de626b5b3320b419a58c844f6d0e4b4aa7308cffd4240aa4180f97b1241ff641d09c90bb40d4d4071f85b913a1a35421aac0be77db6c53e964537ca6ffd8795f21345b62d37a50a6544420f7142d54e6440864a0726172937974a12d775f69037266f501a9120fa31f71dbb64d562e11749260d4d3b3ddec8049199e0c34593dc34b7f5f51cdb963205ff57250d7bed8856deebceb18e8bec50dc74e9b3bfa359f43fdca881c9412fe5c791a7b0e0313300d6bd0b9b7177efffebb7aab23af990ca0fdea4957c2412ea51a7b72efc6be1aba08ed7bba5097be312b4cd3e684e47ef0aa96a5bc18da275bb9ef77f9ba05f4eb5fe1d8b88bfb7a8edfee8705dbe213005052d6c137ac399fb29c5c146bfb371a1f994f0b0563e5aa443167321318bb002434a79b2705aa24cfc36f7f748128bf7e38041a64cdc5459f2446ba34ce73959fe504587b5f5c2f91d2b5b9ded36724cf7f375cebc67dc5f3c5eb37a9d6095250c82d414544726e22392e9a7859898aacfdf18d2361f55139d32dd4786634ea2f59b0ea8db2f03ec335a3d8add4491c3377e3d5113b59e79360d816ec53834c8994ef04f634368d3d135aecaa1d54da5b63b606dac31c5969007e501360e60559e6f01c25a608724b13b978835b4cfcb69ca2deeb2d8b6235ebce9b0123ffad14c4cba462e47c54f7a5a93c5c8e1abe257e21ead4a6216a06aa454a15f8780c1632895dc497062048f04085e360918eaf7d800d4dc7b9907adb5a1efd1a982375792ea5c27d73bfb9f837dec8077cdbdcbadf95b02aacb8b88a725df65743db5a59348bbce2bd46a80bc9485aba23500f03890e8d114153bfd037a87d1ae27a7576d86bf435373d021c85a2a31cb1d978127f89fdcb7ecad2fef36de77ce19307e4ef1ad6fbf2c23224613868c184b318b77430c5e783ed0745c9b76e635fc808cbb62652baef12c848730893b7c6c3c713711f6d7819c8bbd126be7c743e66dfeef86b13ee6d74735edd1884badfa8dcad7107d86f841f69aeea05b28d75670696ee81fc34fa3a822b31a945141c56ae5154a56a04353e6a3c120d47ca11144d460005c75789e5251a225155d3655f6566dbbe26e248532ee4b5345c97b9eadb6f4bf629eca64d269eec8487efb7f7557052490d8fa144f5c0deadef6549cf5c167a02f208f2889d8cf9f380cea5960394ab163cad4b7a56dfdbc67be3f0e915ab030bc5018ac5f5a636b219aa00c077a22437d975689cee84b2b2555a3d5ff145ddf2a0e27b724265cd60c4db153e9975cd8ac5bb5658e5f61cddd821c31c349f770536be773ddf11b42d44fc22d5f954617b49a74e998459f230498e428927e875afe309779aca4bdab38eeb03fb8345b58ffac10a7b1e862e1fc9eb44def447a1e89ad707d36cd9d74f5f38a36251bdef3adc807ac384976b7c82133ff8d0ad5041116c428a45c9447934945def2f008aeac3477cafe3508392bcb5fd3db35a589f38c1b944e079aefbfadccc22061227936566c1b662c62d3816324582058dab11512eb1d6bbafac7cf7bbc4ff88801431ba5b14146fe27456e67fa285b81ebd34cf82fea2977dc70979b82f03d7e17815cf783b54e6e5096609653181c94dc8183c8b5561a8f8a3790f22c261ef3dcb7eb8c7a3eb0f432f016c92e0ee5084d121cfdd34b214bf7715de4dd6bba38d05a90806787cda65aa739d41d9511d7e0bdd9b6395f8b205be597590980a17f631d877a801c469f2e81fe6a44b915d89b04a3b35f087517be09cc2460af73d34b9c898ebe8dc48176316b3b747e1a8d6e0fd7d19753ca03b5c3ef1d0d9122e7c5fd373bbabec86da39fc3a223d3de048b2519fbd892634821dc195c011c078eddacde76fcc1a728906214e12be5901da2739751c2a5aed665b10a55b265e80c75e6d11e1d8ba9ae2e27fced1234b11ec8296eaafc0cbce4d65f1750a6fd82cd3fce774d66249d0d4e21272330cfbe89ab722ee78ea6ccc3113f6829e7d437b307b6eb0cec0082511ef8c69492ed46752523d5e4bbef2799eb76940f4035c101833f7059fa4c9c7765aa0d378c96982e47285aad8a2c5dc33303e2063166c10a8158f5e9e0b86fe152035d767be0dec7b4fc97313bd50c27bbd2323aee3d8b508a2fe395024cd8331996fed16f97ebf70ecbe997de5b8bb888ae8e522360097eed1c96fb2ad50af4a2a8961be88b46aecbcf31c573d5f172074f20e98d68be6129a1360a7c8dbc0dd74a21d936deb873d33e66f8d8f6ba73d8a05a473272b249025a8ad5740f7f37aa5661efe6558138d8487644ffc05f952777083ee67d180b80b1128a3a1b93dd3aee189f9eea635a49da7adfa127b7e2e5567e3e0d58efb6ae588d336bf38121e6f5494e66bc1a9e1f975d596468563f2af990bf08ec933016e9c50f086904f30ec130bf4a735d7b414d1726aa03222ccddef29b4ee69062e217928a00eb0dab678ecacd601ef33d6482e39bfcb04325289f7316d38938460e023ed12f38c38e08fdf6c75341909902408a5fe8786c25716683661f0060222db5d9a1188e9624d6eff0bbd3164adc28d6e09b339c0d825a6653503bf7251972f208cfdc0bdd1557f2f9892f3db0a9efc8409bf6c83b2e31bad172cb2dd95ae311d873bb80e642342814bb71890b5ac9e116f0f367bc85a790839e8dc1dd52b167f6abb3809ef2e8a34f6dde611aa4f75409f6c9e0bef4353d1c2c50df590130365e20204ffe392ee3438d644b8eea3f4a92c3184e232745957ffb88326b7846d4a64eda2cdd5b95412235e6420de10158930f675900f9b558867afbe6c182e37cbeb3625d88adf0dec9c8a3a096dca43b3c7e9eaa54384f4f987354407f2855f4ee5746ffcac55293d9187a668ec72c12468f588b7088b069b20aa03cd1ff3bd9af26e922922e327ba6a424eb0aa9180cb60da4c45a6b76aea03258818d9010ffb6ed4fd0e4453188513a15382e4e057708f4ef24d57d00968009c1022f3a40acca9dfa5523d7fd3e63603f198a5c72855e1b6169a333925fa5c4325efab41ca4800149dfdc8ce7635836978f797bdebf875294128f3ad72ed91ca8b52476f4c7e0c67082113d2dc327a4f6deee33bda8a7db96672b990614edcc7138cea1a006867ff22528f8eb7602720c58564cc8a9cff02b404355a03d60f03fa07cc74a6ba70dc4aa8f2122e5b7863af835ce5fa0e80ce1e62534615a240aadaf1e09f8d201559e19879f6f7715cc459229784bd67a3db8e6d65cf4b149b678a89661b3d0a2f22709347e28ba2bc4d4c408c7df1861266ae1fe47a32c22eea95164a42fdd9070e4403f5a8cf39bcff30f97b7dbbe54cfe09f1dde66f84be59754555e64af1d52508e59b97110440ae59da8cb70f2e7c551d3e41b281b80bead47668dcf8e7f1b2abc09af9af89f51c8690ac965aa2ef6ef565a532c7a0aba5520c41c1d365326a5d5e6f1b6796ccc828290e18a502c2fd403d915f96e01cf1936703ef01a781d7f48efde73d99e80f551768f1cab025f176cda4c9222a074426af4f94547b5108b89534344424f1985558111b570ca48955ed1035af01a507e93abb177447f778461a5908e5e1040b9ebae6d1d2f303cfb463d9784cffc3a95c6631b318ccd952ae9915c6de13374446cad492f84ecc36a4a95d520a76ada6a5437ee4719e73cf997b5a3a590a68356419888ddee7ba6db7288c36d5aef6030123bbf029f8ecb8302155d4160ff4c4c82cbc3f97b463791bbdd561431ca1fec380b31b5fcbdc920e634bd2b42eb8826d96b605a69c60c92a51359ab687b90b78ae6d94e51b64d721844b8b73a71fd1f201c41f2871e3a6e5d0b0e0050437938dc298f241974ae1c00e90e72e04c6ca294416c2ea243174076463b027addf5c423a93bbffa08893f9d401dd970ab0a907ecadde16a41bc95d492dfb8ad2d7ba7f96a98c30afe47011501608df033bf1d49b1b5135542ae8b0f6e556e0e49a9883e4632c6da8f6f4734e2754736280e0979faa883c5815033896644361363045923b8774b8aae0241f2ece112daf259ce072a1fb2c236913a52a9c2a9ad0b2e3a74a3c612a654f313b230673161bd54f9c0c907652a4a1e13677661fead894b893f8245525e6e39d43e5cef2f5686b07c94dfddf62d35f9c256df6c71ed2e4aed383cc6841b3ed6de8019ba6464c6db9c7c7156fe67b899745a65f0fe624b25a2763b7453233d522fd3a2073309ad4228452b84367d229831c86156df0e04aac208b9433c46d8fd03f252453505295ea122051b1c263e474d727815adbccded041f6f7c84cee34192dd0e252e33526f81cfd7db082728526497b3b7bef6ff2a42597f91c6d409415b77819aa8b9dcf02a2a2a2a2a2a2a2a2a2a2a2a2a090e1518222d343e", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 21, - "comment": "signature with a repeated hint", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "8243e3f28052056de7cc4b042fe1d959767644a1b000c5fc3cab98cd8d86670c2025a62784c13c5eb0f71b9546dae058ec5027d4e6ef29dd36e8ac6ba1dbea78cd5126919dec30e8bf50e9034aa5582d522bb97d30a7dbfb1af52d9cb655b7561a17a9df3d09b277849b0f4106cec822d715bc4dacea258f60f4b9adea3b394627b318d2f305dd612fa0826791b03c0a55f456ac9b8ddcbc67c88b6e07375e3aa5114a95afdc98e1167e7cb1c74bce4c835d1b47cd1be95356cf6abc3c9b36dcd2ce4b0267a1e0afc0cc9b7e3d0df7111efe0f936c79bb2ec2b3e65b0641373ba1096bd1006f19e0fda9c7d8082f5e09ae1673cbae86caf98cfe853a2edd27c48fffba468dd6808b0996cdc5eb50f7847f80e51f353ae9afc4a0008248901c25b5328dcae28617d3dcc9556f3e1bd86000e1630210bc8a6ca56d4f0bd61ec09b0ed6d4961cb56ff253039bc8f3b4f9e406ce7e408e8861e599ad05e238d214fface8605e3a3e2173d4b5e1456edced533cacf7135e0d212c4934982072a924074dd6ff9eb3985eaa4e108799c5609b936e2a0dcb32369ccf34766462dd2e310e561fbb09800719bdea3eff789b64b3602c2303286499cbf45cc769d8e955c2a0bc87e6dd60a94284fea121540966d1a8cb893695279771a12eb8b05e33cfe1ce5566337bf90dd241d9c31fb07c6205940b77f158a7250c5698d6c5c251e787bc81338f2171bbdeb3dfb29b2e9202c29365f33e18fe927ef0919482260c01b2fc94c90222ba4dcb14723dfbb3d6fce66da6eb6013bc455848e5c2e3f52f1bddc5596d4a5f18c8f9085b3f25b4d95f8497b818808e5628f94f03b4d838c013a3c2bae7498ed2f23449d77ce94069d2d1c50d12df6d8fb8c8f72b03bf04a3df67ce2990b56595fec781ecbedced215fc0d0b5e34c10819c242a122a4deeb607fb9d3dc68ead4ee07726082d132beb524ce9937b66ef218c221d77cee77ce255b5f18e7cd7c3e2ef9afe80c7bb6675128c90cf6b483d96bc6156f2b7a4d4c98097d2b3086519cacdc3bf35f8127cdd071136b889f1111c0db2953d4d47f8a9de23df6372d65e25b4f8887b4553ad11de8ffe01264ee810a5caac6cb214baf3ec4e5062bdeb0f892014e3551e1e8f5fa50defd5bbc7ec14839b1660d2b5afa5d67a945989f934205902b3c8d62a2190621c6fd3f47be0a69f68b61a5ed1b2c4ff03c7c22fb67a621a64889b1bdf1c27ca1c7322e6233d433cf9bf0ef2c3877bc9780fea6b1a7cc15af6d370e57ef36ddd0a612f1f7e25efdc7762c70c9cd925e545672ec8acdc77872745c7fee82c572d34c9341ba176a2f1e4e629bd1342d00d8bdbc12eaf17e3c2399057ff2a6ebc7834cc80f3ead92b86e0c9cd0a909eb074d97e7783074374454eeeee970e8aa7fe4c27eccc340adb62fc838fd23554554e62c0e4ee0a50a1f2cba806b6172dfca4e3943d4af28fc4e6beb054487d47f26d0d56b8c0f70393eba137c5f3c278438d264d35ff2225f4b8400ee97e550d7770637745cb7ca1cca4825cdcb9c9eedea9bccb9e7c9c2f43e5b95892422514890c465a4784ac10dfd3c3c5ecaeb4f74d7c7c1f41b2ef8a6e27879ce049054a3947e2f71a36c11f439af849bedddd2d4e23fa71857aaf34d8a082d034b3e6a438bd195e07c9d9a0d66a10a7c6a93bd9346314d8ba8ad5b2df800db47d38266b5052d82f7585ff57c9a4ab2f5c09f95b2e050b57e3135fc1b3832d86bde221baf6996c9a95e50984c7a2776a948f4ec98a21ee77507932e8da0fa1baaeeee4ccf34ee03f62bf3c267b3e02c327ec57c17e4cb2ef1be78e22c4090ec356c0c9d2b729b44e5d74d1583aa73de3d2187c910c5f30cb41586c014e1e44fa91c6155c646ead2f60e42017156326d8a4258addc65dc2fcf63d80c9d504d77222ce363b313bf396cffd8cfb802bf6c2f99e5e440fdbb374900b569a31f04e2ccbcaa29985e60c980b75dc8167e6526825005b07ee9dfe7df419ca5660315a5ddd47d70aa0a47e9e914f0160fccf4980a77a36fb78f02530dc01a88fc2e2be50d20f6066410671ad48bb65f4eee60b296abe47aa86967e454a4892c46d1b125fbf121c2972575de626b5b3320b419a58c844f6d0e4b4aa7308cffd4240aa4180f97b1241ff641d09c90bb40d4d4071f85b913a1a35421aac0be77db6c53e964537ca6ffd8795f21345b62d37a50a6544420f7142d54e6440864a0726172937974a12d775f69037266f501a9120fa31f71dbb64d562e11749260d4d3b3ddec8049199e0c34593dc34b7f5f51cdb963205ff57250d7bed8856deebceb18e8bec50dc74e9b3bfa359f43fdca881c9412fe5c791a7b0e0313300d6bd0b9b7177efffebb7aab23af990ca0fdea4957c2412ea51a7b72efc6be1aba08ed7bba5097be312b4cd3e684e47ef0aa96a5bc18da275bb9ef77f9ba05f4eb5fe1d8b88bfb7a8edfee8705dbe213005052d6c137ac399fb29c5c146bfb371a1f994f0b0563e5aa443167321318bb002434a79b2705aa24cfc36f7f748128bf7e38041a64cdc5459f2446ba34ce73959fe504587b5f5c2f91d2b5b9ded36724cf7f375cebc67dc5f3c5eb37a9d6095250c82d414544726e22392e9a7859898aacfdf18d2361f55139d32dd4786634ea2f59b0ea8db2f03ec335a3d8add4491c3377e3d5113b59e79360d816ec53834c8994ef04f634368d3d135aecaa1d54da5b63b606dac31c5969007e501360e60559e6f01c25a608724b13b978835b4cfcb69ca2deeb2d8b6235ebce9b0123ffad14c4cba462e47c54f7a5a93c5c8e1abe257e21ead4a6216a06aa454a15f8780c1632895dc497062048f04085e360918eaf7d800d4dc7b9907adb5a1efd1a982375792ea5c27d73bfb9f837dec8077cdbdcbadf95b02aacb8b88a725df65743db5a59348bbce2bd46a80bc9485aba23500f03890e8d114153bfd037a87d1ae27a7576d86bf435373d021c85a2a31cb1d978127f89fdcb7ecad2fef36de77ce19307e4ef1ad6fbf2c23224613868c184b318b77430c5e783ed0745c9b76e635fc808cbb62652baef12c848730893b7c6c3c713711f6d7819c8bbd126be7c743e66dfeef86b13ee6d74735edd1884badfa8dcad7107d86f841f69aeea05b28d75670696ee81fc34fa3a822b31a945141c56ae5154a56a04353e6a3c120d47ca11144d460005c75789e5251a225155d3655f6566dbbe26e248532ee4b5345c97b9eadb6f4bf629eca64d269eec8487efb7f7557052490d8fa144f5c0deadef6549cf5c167a02f208f2889d8cf9f380cea5960394ab163cad4b7a56dfdbc67be3f0e915ab030bc5018ac5f5a636b219aa00c077a22437d975689cee84b2b2555a3d5ff145ddf2a0e27b724265cd60c4db153e9975cd8ac5bb5658e5f61cddd821c31c349f770536be773ddf11b42d44fc22d5f954617b49a74e998459f230498e428927e875afe309779aca4bdab38eeb03fb8345b58ffac10a7b1e862e1fc9eb44def447a1e89ad707d36cd9d74f5f38a36251bdef3adc807ac384976b7c82133ff8d0ad5041116c428a45c9447934945def2f008aeac3477cafe3508392bcb5fd3db35a589f38c1b944e079aefbfadccc22061227936566c1b662c62d3816324582058dab11512eb1d6bbafac7cf7bbc4ff88801431ba5b14146fe27456e67fa285b81ebd34cf82fea2977dc70979b82f03d7e17815cf783b54e6e5096609653181c94dc8183c8b5561a8f8a3790f22c261ef3dcb7eb8c7a3eb0f432f016c92e0ee5084d121cfdd34b214bf7715de4dd6bba38d05a90806787cda65aa739d41d9511d7e0bdd9b6395f8b205be597590980a17f631d877a801c469f2e81fe6a44b915d89b04a3b35f087517be09cc2460af73d34b9c898ebe8dc48176316b3b747e1a8d6e0fd7d19753ca03b5c3ef1d0d9122e7c5fd373bbabec86da39fc3a223d3de048b2519fbd892634821dc195c011c078eddacde76fcc1a728906214e12be5901da2739751c2a5aed665b10a55b265e80c75e6d11e1d8ba9ae2e27fced1234b11ec8296eaafc0cbce4d65f1750a6fd82cd3fce774d66249d0d4e21272330cfbe89ab722ee78ea6ccc3113f6829e7d437b307b6eb0cec0082511ef8c69492ed46752523d5e4bbef2799eb76940f4035c101833f7059fa4c9c7765aa0d378c96982e47285aad8a2c5dc33303e2063166c10a8158f5e9e0b86fe152035d767be0dec7b4fc97313bd50c27bbd2323aee3d8b508a2fe395024cd8331996fed16f97ebf70ecbe997de5b8bb888ae8e522360097eed1c96fb2ad50af4a2a8961be88b46aecbcf31c573d5f172074f20e98d68be6129a1360a7c8dbc0dd74a21d936deb873d33e66f8d8f6ba73d8a05a473272b249025a8ad5740f7f37aa5661efe6558138d8487644ffc05f952777083ee67d180b80b1128a3a1b93dd3aee189f9eea635a49da7adfa127b7e2e5567e3e0d58efb6ae588d336bf38121e6f5494e66bc1a9e1f975d596468563f2af990bf08ec933016e9c50f086904f30ec130bf4a735d7b414d1726aa03222ccddef29b4ee69062e217928a00eb0dab678ecacd601ef33d6482e39bfcb04325289f7316d38938460e023ed12f38c38e08fdf6c75341909902408a5fe8786c25716683661f0060222db5d9a1188e9624d6eff0bbd3164adc28d6e09b339c0d825a6653503bf7251972f208cfdc0bdd1557f2f9892f3db0a9efc8409bf6c83b2e31bad172cb2dd95ae311d873bb80e642342814bb71890b5ac9e116f0f367bc85a790839e8dc1dd52b167f6abb3809ef2e8a34f6dde611aa4f75409f6c9e0bef4353d1c2c50df590130365e20204ffe392ee3438d644b8eea3f4a92c3184e232745957ffb88326b7846d4a64eda2cdd5b95412235e6420de10158930f675900f9b558867afbe6c182e37cbeb3625d88adf0dec9c8a3a096dca43b3c7e9eaa54384f4f987354407f2855f4ee5746ffcac55293d9187a668ec72c12468f588b7088b069b20aa03cd1ff3bd9af26e922922e327ba6a424eb0aa9180cb60da4c45a6b76aea03258818d9010ffb6ed4fd0e4453188513a15382e4e057708f4ef24d57d00968009c1022f3a40acca9dfa5523d7fd3e63603f198a5c72855e1b6169a333925fa5c4325efab41ca4800149dfdc8ce7635836978f797bdebf875294128f3ad72ed91ca8b52476f4c7e0c67082113d2dc327a4f6deee33bda8a7db96672b990614edcc7138cea1a006867ff22528f8eb7602720c58564cc8a9cff02b404355a03d60f03fa07cc74a6ba70dc4aa8f2122e5b7863af835ce5fa0e80ce1e62534615a240aadaf1e09f8d201559e19879f6f7715cc459229784bd67a3db8e6d65cf4b149b678a89661b3d0a2f22709347e28ba2bc4d4c408c7df1861266ae1fe47a32c22eea95164a42fdd9070e4403f5a8cf39bcff30f97b7dbbe54cfe09f1dde66f84be59754555e64af1d52508e59b97110440ae59da8cb70f2e7c551d3e41b281b80bead47668dcf8e7f1b2abc09af9af89f51c8690ac965aa2ef6ef565a532c7a0aba5520c41c1d365326a5d5e6f1b6796ccc828290e18a502c2fd403d915f96e01cf1936703ef01a781d7f48efde73d99e80f551768f1cab025f176cda4c9222a074426af4f94547b5108b89534344424f1985558111b570ca48955ed1035af01a507e93abb177447f778461a5908e5e1040b9ebae6d1d2f303cfb463d9784cffc3a95c6631b318ccd952ae9915c6de13374446cad492f84ecc36a4a95d520a76ada6a5437ee4719e73cf997b5a3a590a68356419888ddee7ba6db7288c36d5aef6030123bbf029f8ecb8302155d4160ff4c4c82cbc3f97b463791bbdd561431ca1fec380b31b5fcbdc920e634bd2b42eb8826d96b605a69c60c92a51359ab687b90b78ae6d94e51b64d721844b8b73a71fd1f201c41f2871e3a6e5d0b0e0050437938dc298f241974ae1c00e90e72e04c6ca294416c2ea243174076463b027addf5c423a93bbffa08893f9d401dd970ab0a907ecadde16a41bc95d492dfb8ad2d7ba7f96a98c30afe47011501608df033bf1d49b1b5135542ae8b0f6e556e0e49a9883e4632c6da8f6f4734e2754736280e0979faa883c5815033896644361363045923b8774b8aae0241f2ece112daf259ce072a1fb2c236913a52a9c2a9ad0b2e3a74a3c612a654f313b230673161bd54f9c0c907652a4a1e13677661fead894b893f8245525e6e39d43e5cef2f5686b07c94dfddf62d35f9c256df6c71ed2e4aed383cc6841b3ed6de8019ba6464c6db9c7c7156fe67b899745a65f0fe624b25a2763b7453233d522fd3a2073309ad4228452b84367d229831c86156df0e04aac208b9433c46d8fd03f252453505295ea12205051b1c263e474d727815adbccded041f6f7c84cee34192dd0e252e33526f81cfd7db082728526497b3b7bef6ff2a42597f91c6d409415b77819aa8b9dcf00000000000000000000000000a0f1619232e353f", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 22, - "comment": "signature with omega+1 hints (causing a buffer overflow)", - "msg": "2b07000000000000000000000000000000000000000000000000000000000000", - "sig": "f939af2cb7dd8e8b7f0ce4b1d32f557237d8d424c59d381ad66157fb06bcf7a057d52e018d59c87a99a19242bd733eb62e7bdfafb440fb9e25103c55521615f9108f11016cf73356eaa228711d5088b5c38de1aa8294c64e53f388adf25b6908c2b4ff391f5c5fae1a9aa79fdb867a51aead45d381ebb23bfc83676aaac1cb0f0c4a5081a1403cff5afda4748fd8c41ab8bdebc257b7a211968add7471b10e72beb32fbf92df7ec70bd4ee6c7267b10d73e157a18a3cb5ace2b65aefef560bd89130f15ee223fdd5bbb9502bbcc103dab62d9fda16134c72573366c2c6bfdf65079ea2f1837e56b8c3b00df969f5665aeba7ffbcdbdf2699adfc7d643fcd9edd18e73bb2c4999bbf0d55541b999f0f3fb33d30f409bcd62c99150084b931c42dd36f8ce2ee93c9e2ba6e5a547b714b560d9f1b76455303cf171e88a8ef3e3e7ba358b452beb7ce6422ab16962adaad21b43b6f57a99732d046e7b8704ebcf7fcbee481b3329e1fa9e02de35dab5fab07af21c0d52c57e99b1082d79bcafaf2f9782612d7ea955878f522b4d74d80bd35e2740088f438258591001f24c58dddf23c4fa9e83a7564b8403c2c858b67272a61305c35cefaca78d5aa755c1a449460fa9b686ec21c1b6dd256724aa54bce1a01fb9ad24d4a227967ae062dffe8d07765e43bb84eaa1d15ff6d38ae9e371bff423abf488ae51ce55131d0caf8bbc0981a2248039439f6cf695d854830763969d1fb84c45e79655a3004a548e11c89341c7763ab4227ae7e0581fc6d3700c27820c501ce93c16f863ea50a5c25b11203d4379a6220e9cee93398cc0914f1f7cdf79760c6ae48e3a84451365eafd021608c9b21512e788d2544219a3ee4e45fba603b6d0393620277cfadd80ed4e29d8647cbfe6cec624a722f4a704644333fab18d727fed94bdb850e8177ed7a211da533e07c62c9d4263e7cf091c84e59dcc2980adff73c299fd442a64c1ef06f3cca5e36331f32ff374af866e775ccd433accb095df25bd00e19436462d5e92ae3106c67bd8b6ee8b33a2860388d4d8e0b7fba47974064f5557e5d0c3a94ff783d9796818b37aed96510f18a1dfd03b0d4717851810a7a47bf5c334ca48f867a49591c766159b09ae75540ab10d93c7c559fd10ccc3a218d1a89dadf95bfaaac97e4b8ed60f705e493aaec20a5182cb861501bc608ee21f959f29b874cd77cc5d166645167eace927c6c3406b491139ae530fd595ffcb7e1322faa6385694e6c447bd22902d765fe3bf392ec7d9d9b09575218c7dd2c90f7cbb357e476f32a7175dcc4f7c663b34e456ed0f8f7b9ea3bee91172f57406cd8986b4c949fcfaf8ecaf29ce2ba1618424456e901439944604ebbc2c0b7fcb77afbb193c56fd7e2c074e1411c97990306569083ac9b718af7b4f1490f15ea05b7e73f8e86a0b798f5bebbdaf4c08a94a6a0aba0b690490c860cde3647d9ed8523ac65be33e5c8fcf044d62c662a61dd01a8ae49fb56b3d4878cf3c0c4a93ade30d544f76c38f7dd29687f37a2af933642115c2952f22563e4a73adc93bebf86ff977a23d50319615eca5d1b3e6642a3f69cf8fe9d5cd507539ec104c02eadb84579c3db4ab3432651d34fa7cec0c5bb4dbc16df6fa2a703493c9004d9bbae2be40259a3b352572d8a74ae86fffae2c8a63c2d74deee41efef8bd07dabd956d3154a3bd4e60e37d97b89fb7d14780179e19cadbcae054fda19221799d91eec1fdc72bc836c13ba4c42f52bc04442c82d3f0ecbd00e611091f4c9d2e3491d4045189ec44a8d07e3bf51ffbe59e48b1d1cbf738247689f459744637540795884e28c5a3d48a48c1eadda076b78794d0f281f41dfeb50c0b4503f9f1f14f68872bc603053d9914751fccfb80cd5258ccffbf75724111292e03ac28f7373577c7e6c6c80ddd45cfe778bbae3b9ac13caec792d103ae988379e4e7854d2e840cc50078dee8c8dbf6460f31de92236a886716ea5123c96f48e095c445e0f291f5290044cf75b9610b1329c560ce327b541efe7b32fdd0209b6fa5e88bf1ff061b955d3e8c6945f85020f909718d66426f731446c24eb226bd0bad7030e071eb0df3992af86bdf1ace76995f89bb0b4e47ae3c762707931ff3d8815e33802bb867e768e7ef3793df70f588dac73ee6e27ed5b2671a0a080898b2b9fe20cb37904698e6869061f109d3d4f50ee46adcc24127a6e9f6a7b520b4763bb7485fcfbc278bb22c0eac2d963398d62f1f18f48df90b8503b9184eb90efabf4727b72352a010d81ff32a0aaf1c6033e156e3e7041bbc39d80e6d838c18cc7dbdaa181ef74c6fd4c2595b01743615fdc2829b948354a8b81e0079dda6e76c50b269611a6245649de0485c91ec6112a9bc0aa925e7f7146627d434184598c27d2457775073f340392fd44095031aec0e6ff77092e848f5c472f982e0004bc0248b25c3397ae2702733cfd9bf640fe179a6b9276420ab780858c23d409221a8f3b38fe686ce6e68006c11043015c0e1cb87957fde4414d36ef2db4259754393e8f9ae271b3930f68681ac51c1c0cea7ffb617e0bba29cb14e011bb4bb53b4ab81503905b5db2f8253bc3fa57d31187ee8794a38f3e3f5e8a5a5bbf7602ac528af19469ab9851a009497153358587093cb3e002b99f78415fb3d0fc49c2e955a1d36b088f08d21eed0ce04543ea455011ee90ee9e47ff8e7027a9e383f249203e2eae90f3e43f05efd4ae990cb665a5c882113b4884df4f6fc0088630ce1604b1dae5d4095b28a51ce4c6a8e9dab1d6b2ceaa31da967b225ead5defcaea6dfc3d7d689dab369638d789acda91ebe79ff7ecb5559ddbeabf5226618dd53027bcaf51f22e52abadcbf81364687d32fae1429b52001e9b25bcfc84932be3ff947dee1323f66f942f904706cd5f905dd7797a2549223380a4e093cf0d3a253bcff6fb4ee3c610b8a168f03c9e559b5c0e2cd9ed7d21e4c97ba1f1eb71725408a4e8ec5c25e3390d076e08fd4b5d80ac04ff94c381ea5f1473f4ffde50bda0f58d1e54bb6051651a8c5d0270262decb7db46850775f0e43c7842fb7a073e654f55b4d791e9861da2b3f92682e1155846b3517c976ad9c054128c1951875bc40f33cf93cf18b44a545b0da34185f2580021692f57297d7c790a3e22964502f8fe7cd03ce0252b52d5080c4ac33ac2b2e1f40cf2b93df0a97814ae23347abde56a827b02839234cda1df5109e4b65ff6b141c68f72828fc13e92a30f9e632bb2c46a1ad4ee9442b0c789d4577c0caf6834f66e721e7cc140d60b6844071d7f7405f402547ca60f1b4a752eada2aa93c51b49a34d3606fa085702e220e07d61aa8730a27d155bdf61023d20081525cc358de329444aebe7a38941a8a099b65a4aac6b7f1c960763c26dee825b114e32b9e9ecc7570546771bade0712d8e35ebef2fd7c945ae4fa034d1518adeee10ac5a47be25cb280f09fde32e70e031c161dff2a529fab31aa52e6886a129c52f9ef2edc61e10b2b1f238ea15d40c99d07c1fb4903970ad2dc5709f3e5303ea92ef387a92133cc673468e36d792abeda921b6a0de018206480a895e2a57fc119fe6eacf9c5e511a7bcba59e74837214a0e4247a299cd94d53696617424ac0824c204775735619c922eaa5d7d5ff50a8b2715108f6db3dd86500f85bbf224c0c74325ac0c90b5f6f6366d69abdf1e834836e98dd1c7d51a2856a4ca0b7cca1253e28aa35d9764dc40e4520127bccdaa22ad638f920c0b4864d1440b34588f952957c769355165dcf13c2b42d660745e5566ec1a70602be1fb95030d6c7f162f13850a34a12b9f729b9250dcf68a7f3194e8e6368f7a2c40e859365936ffc0880bb818c7b406cf5a89c454dcdbc43440dccb2608baa931f69db2dc5b334e7cd35dde10c6d35ff62d168931a4fbb3f970eee382bca6c3d4ca7b739b082691bca160be4c675083008cedecea2f6b882b338df23a9dc5d9fd9ed39a84f9734c778e08e75a264592aa7fbd2af145405cbb03fd67f38ac840c40bc49cffc9c537dae44061ae4507a1b72bd59eef7e5ebdb276fc8775d84f8bb4d33a731b077f3653d1331bfdff04274e06543ea7b70c5510aaf485261ffdfbd8dc5f7c53a4f5e04b2105c2cd0360029bfcf95ccdf31cd8caaa417629eb1840f365c0c8325ce1a84862d71ae1b47aae9da4e4f7900787c789a4b4b3425dd190a91ce9f0552b99f98f5f8a79bf0b2fcf9d5da773970334212de70e33d2d58998c8f20b0e56264259f82ead020ac7d21c5a791bf2f1dbcb4c8b724a2349af0bda4a6f24b80fb614d75d84d2bed19dca2230275b28f11590231163907a3bae05b8e08ffec1f66904b4530c55e7909ac628bd7bb70d7079980bcfde761cb5f45a4bdf7ccc1d50becae35f6d22b1f3010c03fdca4ce46896ee17b630593e262e316e3be3f7dc293aa2f5779f4617335820c64258cdafe432b6c50d63500c519196e2f03e581157da3972f39ba44a80816e0043caa5ef4465dec72789ae7b80a2abbd5aa951e92a2c1dc413424840eb519075f1a3599dfd0bfc2a55c11f1a9592ebd6c51cb8d553e021e3fbea0a64258a807cbb81131b4c61497eb5accbde0f4466e12ee95904a709dd4090309a0662e667e0f891f02c674d541971251bc803819e9791b0486e69c6396109eec87d6e6f8d14c23fc6ff117ea0c5bc28721cfe6e312ee8f62ea9c6519ee242f581c0c96763edd10f4b457db8e01c77443138f1f69ce670907335c18a9ff7b249be0fd019201a78a8ee24a356cf4780a2ae0ab83d6ca15a3f030f66e63a93494d9d0c0ae67fc1125418e304029b0cdee3a802cc06c41d107a5b962516ed710985523225deeb817a655bf80b6ab0e7ab9ca4dc1323883ac8ea2bb9ad8ae4c1a04158edc7975229166077c181af618b70f1f3e7106f7356ac8780b488b1ab0fe14e26d92b9d55cfb4bb19039ab1b1c2e2bc0425f6b0f74d2c55634a387d9fb6eb2e6fd6ff3bb6b16a8af994f9f731e651998bc3d55b1251f2d4e571dc7c4f2a287841e7fc6364e6f46484cf4f797918e1e9a09873e19bc6b59b5c1394af7c2571e30da78cf24dfa8beceda8244e6734f242a39e7837be52da7d0185e5343066d600869c8cfacfa9aabd5789be7b8f2a3328e497c01bf0a59ef74aacf331a05be9e5511d6e29094e88235560fb7c3611bd8e0aad16dbe065fbb6f3412d0dc55ce38e59c9573d39205d3fa516c3da2369a5680b825250b76919f914433b067fbb330a1e1d736e11e35774d27d397f8ac9af3e2fc67d25f9cf444fb9ae53b954b2ee90c0d808551a95c99b9395f06d7e2ffdb9c8acad1c4de696a03fd3a41be80cf2f83013ad4cee68ca221954327fdf32b3faf675e7817c323b916a3bb72bb7ef7f3a24c36de94e047cb189aa055e13e1144416018b7a3ff742e4fcabf7e60229509430cdfc7ffc258226c5eca8104824d48bbd5c01e3293a38cb37b329a5b694d529431caac02e1f6d953c48059286e9a6686b2c8502d7fd466c96d965198b8edb33a29c6283ecda803214fc980b7542a9afbc776a4a16df1edf30743a1f36051140d5ca1687ebf485ac90c1ab2c141884e30c845533091c85af1675bc83ce1f7a86e5cd7c8c092b7187ca94c3663eb707be93ff7f35c92418946638a4a9a159a8ae6b47756dc7fd6e96f1e7e3742517096de075027ecabf2069f364d6efe667f5ee67101c39cf03ba6513a1b23466a9750e1aba46ec6dff6545959b09b08fcbac3d0c89d9335c37d95cea7b26e2b580d54ead56813ce13ae0367564246bae5f088d115244ce9ceac7f669801ed74391fde3cf7f0a836d71197bba6b412be3707851ec27aa84af4925b49232a4799fc435c14aad314925ba9b5545cf95d31f1610d838713e8cfa8d6b697de8cc7127c6fd719043aa39d88434602c759571badaa5669182c7cee9d81d592eae4a7eda0eccd3f6a19f4dd070ce1be5946347aa65274e59676e65fd823eb1138c30f141383c52093d5dafd39c03b7b23fe31f696a5c4711349ceefdff6c1a6613ca121b5281d5132205a22b02d22ea086765fe7f013939a8815a41cfe2529f0524e7f2c23763aa8fd752a1d6eef6ad4168dea2272a61381d4a6ab003d6ab518034a0a69a38bcd6456acda639a84812960364a0749824165d141ba91f2ad0473c9225551910f50818810fcdca8ff56925d15ac0609e075904f896eee487f554beed7648f4e6f6a531025f1a0b5a5edc97c7edf7ea363b1afb715593b0068dfe4a396611a239b11c2243ef30d19b8dd29802f92a12cc99a3711ab0c86675416c4a6a2787eaa2335eaf7eb517c4d30717d499b4751bc03fe954d7cb2f33b177e46bda5b5a9639abc0a2ed722c3e48e133e9546a5f28d75b3d37d07da8936ec2e9f6e46b1a1c6a797e7f8dd00b0e5181989ea6a9aa272f62747c9cbec6e3e6ec293e495165bd0d111b4045506f85d76fc2cbd4d6d8e7ee3f486084868796a0a7b3b4e8eafe2732383c3d5ddadde8ef08111c222b33414c", - "result": "invalid", - "flags": [ - "InvalidHintsEncoding" - ] - }, - { - "tcId": 23, - "comment": "signature that takes 1 iteration(s)", - "msg": "0500000000000000000000000000000000000000000000000000000000000000", - "sig": "0229bfc4d70e9d0e467f5ea85a1420b00b81820e9a13649e8e2cc09cc9504635b9c1a949d81322516c01ff425a057dbeb7936e22be2a98442ec10530cd8de40a7d675c80ce4e56bd588f663eed2dea35de293ebe64deee37cde062d84e6913247125f03fc650c43d0720a2092c87c245852416d5ce9ef6d91133b076a92eeeb57509f981e2382e47dd5aad2dccaa86bf1a32fb7285ea4f0bce2368634d7602fae8a9f4ac368341a06ea989e6a09d788b3fe0e832525e52717eeb492f930bf7d19f0ac0ddbb2581e6a018e007a89ea03ac280b15b556ad99bc01eccc5f2eb3f2f860be25527c2900ea2e69c99be89b542b8320717f353ffae0ca5643989fc7fdd401d01db89ad430eb71a090a32266f83a004d288e728a1edcf7de82d4c9c38b23774a851a600193c06f43010e4c9fa9cd371b3d3364e6986199a7fa37cd26facc7e4f252831f4d626cea95054d4236c1918f1580b15ea5952a6c228b58295253266e30d5e588587f72b0a98811209f4dcad14b13779159d7e2f139d98c12d4bd7b1291778a9452b1c4e73127f79a8568237d73fd29b952fe002d16bdf26d610ab3aaeccc6e9f04fd0e93f033d8f5f411d9c1d5a5259ea2c4bff57afe34305af8986d05ba052219873486816fd543cae4c46d9c0f15bbce2f6e9a91277263ed42749db4f31e2c1aa8dbe356f82e168518500f34052f59a7fc1cf6a0066d71fca6ed2ab93ea747911fcc433296d18d33a66ee0b41d3e96edda30acefb1b5de88c8029dea379354b58275163335d761ad438ec5bbe72950043806e3c9ef3d68cb9b5ecd2d39053336c435dacaf4b19e1dddae0c85ac41e5f71183625e69bfba926165d844b04f566cf61058289570e16057787341ae5c8e409ab9d7a56a94d7918d3a20859f5d3480af8a8e2e667f23e7b2ca89451fb133099acdde98c409c38cc81d8b58442fc6f7576f80fedb5810635a72eb1ec2394f4c4bb5645aa5dffd16da9ea95ea5cf8d8fc5e352a4bf5cacc7ba9a1824ef630d71def61ab595c4323689a28d828bb457bd98277a7a0445ffbaec6430e63817b6f26eddfbc3c2b877bca8cf5203cf33adefee99ae4d19f4dcedbf4538d2bab743463bdd6717894ba5d476943d4b61072de555dc4b4ff6d8876ede52cb61414f1e027ab15205033268c28bf530fe5ddc54f94a0acdbe548d848461f6302eeb68326152176b72d7cb7ab1aa219bb0c737a77fbaf045114400d4f805f2a5b4dd11302d763e229c5631d14138b48c8a1d44de35e910d495bf26382d2b449793eb75cb9b8cb7ae6473550d033a11ae7eaa39f216e77075151cda2723c0b464838f89f6d5ae9b97996e3432abf3212720f67882e42e538c63c02b9063504722561c2097eb3f07b28d87fdb8e4405dc98470db1266a948fddffde133e287a2975b7bb5d9418fd53d68f6dfe05aa943c7c573cf95499682ecb04f643afae2c189532ddc47af8058e7b28be7b1e3fb8aedd628b5c18e31888198a77e29c93d0c3b1faf56fa770b89851042060457ce177794757dded3804983d6d5edf727ee919cbcb442fe966bee94e3eef9745d9b2f7e5f75bba4d24e6a810a7174cf45b4b07d6e5490427fd47ea2cea9d11c5338842974f1bb6434e98fbadd10f70d269dba8d385a46301f5f96329b2ea1e33f78fab2a45c7cb94ef74839edb10d3796ff8ffa47d340ea126d2c929f0f2729c002d2c85b22514db13744525cf6b6bf34595f4b3ef7c52288c801568876884095adf51ee9f018ad477966ea91deea0ee5ffd1bfa78497072ba07bdcfd74b27118051c726b499af21352c16be54d847d541d236fbbe1c58ef6e402f2fec60aaef04bc92f67b5bb1f85cf8ec350cd9992ee859608a2e09fc73b8a8b61366d443b004e6b4e38b785bd7c086f5e8837846393ede07bb21c1f467a5df702a26114d2f95d23f2e10981e8631481dfcb79a473c510579db1d642fc7acc3ed2646fd6ac85a9fc346892a528ba5b7d5bae904bf5b44191c30e240bc055a783b809fcc4bc2d8fbbd70d940644e0a5abbee7646137e04bc8b52fd4332addfb18dff61cd543131cf5bdc4569be0c8243c5ec983c97745ced735e6612b103db25b628bc0a6f6c3462e15993c1c51ace3b8bc04e7b8c30e127b2febfa255039f19f72387cd5045a9632637d4df4be58ff7f6a5e0eeb1415db542c354b1e3414ab14e32f9e02c71904c3c58d342a1143177acc661852a7ab0fae89bb484dceea942bc0a70619ec906841dc8afbbfbd0985f5f00eb28d57e27fbb35c3fce0f0d745f648b668a84c8066baa438fb78c2e8e909dc2bd3d17cecaee6d1f7188189e796c287470230427ab16744a4f1e7367a1544d85c7b914edc5dd893c6696d360d82ba1cc278abb20eced305fa1ca0f32b51d7775d5e3b23fea303e9a13bd0ef4871437e1b68e20afe244e5c67530193e9c388e45d12c1bea033626d076ec16317ad325f995ce462a9de51cef002c24084f5c1a15f2de2e2bf2604a98f3a1382645abbb6727c464078c402fc43c0a6f5519b49782cc38255f0149a3386b716702f42552ecfd27ba7d3e34ec7906dfa05feb6483604cc6fa90289ab7572ba19bc61044923a67a41dbd40dae5408ac3c66b7974f71e10a4f8cd23ad2f3a12e1f8e5cf13aa7faeffda6d968bf0942f7dcda760da182e3fd68a1a551b592c2f4b29bb761c23eac60c7cdc4de1f2574c34818bb1cdcda3242b7629b6fbc18e297fbc5383b099a265afa93a1e142975e9b53b3fc04dde18728f656659ef0e58236dd5fa7baaeca02dde76d477eeabd3bc3b6a043e8f85c216d434a4c34afecf52e23f24581772431bf6ceb4a786a34376f6d54e1aa3c8af2b107ef0d6b83dbb171aa3cdcd2f0c4e07b25631a4893be71b4982d4707d6d712c9c73a357849c05afc628d2bc2e665d6e6e1c4b9b3f72d08bf4485006418de5edaa5c5317431cf11c333c2a7496781ef3a84ad895fa79157bd3060852f0b1b7b79782365c3dfb04f409df6a4da69ad68a58644877696de0195defb6bc9d74ff8f7e9187f3b9b18902f54bffa248b19e3cbbce4a0980f26230efbe6bc7d07589aa83daff2c0776e70e56d443dc3933ae796882c142523e85fe3135fea8c01c527e043a504e9d06b8e615cac375f755ffca055d8fa3cb8140078bb077f789e0087b8102383ab7ff613e1f7e091c3df36e8fb27ff4f37e1d26fce1e4841a02c4247a4691ad557ab7daad88e9352ee6757f9d703055fe3509c20d1db87f898bf8bca3bfc24ef770f1a878dfc5baf45dcb23723ed078242b8ee8147d475e15949590cb9b7f6f7551b47116a67044c43cf24a12fb61d56f2566dc4c9bdc60e1f9cfc79403563e3338efddf8726a83524ab8c42910c5703753fef5e1694fea43382fb60331172f474d4c9e99b4fe2ebcbdfee2168cc389480bd2900f77aa977d2b5afab48c93f43d0f036e5fe189c16221978d8231fc6d5894d29949e324e223543de97e8fdae8fbd8519c9b084f4413d69e771f4032d52c522c3f312de23cd3b7fbe811aabcdbbb161378327e2ab6ae6810d2cdb0dc0df33944626962f90eae6aa9f5cbf8efc87c5098ddb6b4d49c0c480997d9178518d93a64e7ab597e2a3a44d5a592e0fd3c92eb86071fba2d1aba92de203f33f449500754c09a22b4a6797e9626dd0797aab0f11d78989b04926f8632b517a11884ee85b2f23d48c03eddeb77df57101fdb1ccfd767369c9712c2e5e563771f9200cb102f44557d3c8559e21b3f1b6ce984f3d35ef3881a3b5fd6f3d49abac1e1a0ea3c4618556a71d71d1e7b12b86214b67e7de2e35a927d2e45b50ba4944f3bda17591388c70be711ac59aa1aa2dec1c5155ae0a9baaaec95b4c6220256004551faf40ad49101eb5d2f95386e6dd347645f5894aca9ca0b5c113fad4fccc79ba0629bf58a0877bd32ffdcbaa50e4b801b7914c05c0ffad907a4d2b77a9dd9eb567206ce95c258f045b736913c9d746c445864955fc4e0a50d5f06908f3e6742946444d0ec7c66c406348657f2f68f5cda005e49a6d8d195b7b7fa96d13e0233bb3e37890d36420d5e77992cf671888ae5f81271584bee49a90351523ecd03786ff5d625cf5cb342b260c5052d41129f56013a7612b4e1ea94071314a164e8d1bc2bd457bb02168c587de74780ee7416ba540d4a730ab5c5e5bb72f55e68283f8ab0a86bff92abb07b799cbe3024319264037ededb5caf3dc36081b6d68e4d56929f3025a274bdcb3bfeaa5fefe487474f614ab5443645d1c40886d35815fdece65d70b06c4b89a733c5a72ccbe9a9a485663e86976a1c11e23f274f3d6abaa16a10bbf24932f3807b6cbce58a0f2fcfd13acd9b131eeb17d00480ae69e9e47f85dee24e1261d9157498e969624ba398d6b8db92186903daba00a31ac8dab06e416f638014891dfb8a6a2e4cf724116c5b74eb255ee14f81ec9018d01cb2243c6de9ebbcfdd381bd657ba0002705a3fd7ea28c63d8a30a7cc7471021fa65da1641c976eec5878ea0d7efeaa75bb8e0bc57290712865356f76aed2651e049c7744e9f8940c6f52fe125b5466a9e2037e1d504e9ded4bfdc44cea88392f10e2110ef37ac8e6a226214b8e9ba4fe58ccc561aa0d4745a86b18c692dcf1b7b5db04e4099d7f9349262d6df7be449481cf76fc049e9222c324e39f6f9dda3c88fe5be66471a0f79ceb8c5cef5dfb4297e63a416bb1b89d42f13faf26e073989d1020a2a44866f149cf003530b369fe16e28966cc08dda12f32c90947d817fa9f8a19710f2b33b3ef05d57e32004178b7482de6906fdd8c82678c656015e45e4a382b54cffa882f6feff2fe737fb9c78a2d9bf38fd17db421ff4ba3aa041179c1f6d326bd4122c9f0fa94f99db3f8e9e5261cdf937cf0acfa38def1a31eb41600b7cd8fcd380920ddb588b94a1e28fb40d92cdc815fc69e9566d5d708d3507508ac4bae8334704f8b19efa035a831c4e75cb00d83aa5984b0b264b2f2611c28b9cdf725c4a3bd206a9cfab8ada87143ffb9bdf4877b3131d21f993c8f697d9c2833751876c7e0aca82c645d0199fcc026ea0fff53b1ac7a9639987673609fa909daf59262ffdd1f6815d2ddbce2bb1d31f7118526f394e8f4dfff23f44e6f0819ce113a3f1834e85e2cf44cce38c1ebd5f38b5c69f5402dc5954604c7dfc17547e4e01f94b7bacdd9be22b1bb85c92efc4561328586553fbd0c88d0283e3d9fe5c1ab0ee6d9103479bd3443d0491287f83ffd85b35f56de395aeb86e9433be05a9686d0755c977f40a56fcd98dba1af504cb14d7ca158fc8f1cff114676526bc7161d9094fc9131fa0172b0b8612f49dd6d6a367e84f3e885144c4a544eadfb682161a9b15c128ef133333afa0b5e7746283a408b28505eff4a23b15dc6d02bd343dfd1e6d80606d06d7c2f14d5e02762398fbfaf9853761e4060d9bd425540d20d25fd664d7e61cff0ff038aa2a52b9f84b2e1d9466acf6b37956cbac867c1f068210172456512b45f5f58d34890fd080887336fc17aebc6fabd9fcac3621de78a73f6db23530674ba836c98f93367ff941325c5d1d5978b1fb327208e4099e789d876639e06e4d9c4fb5545dcd492134e5e86a3320e7f33a4947ee6144a1121ddb61908f9f9fe4258c355c186b95a9a656d52fb774a7251e76d4eaf746effb7e9d900ea61ebd47ceca6af61dff6c9554786b3065319b5918de4fe1a7d1f9f41b188f274fdf684c5e30b846211f9f179fd8b847b03eceb154cb4229540b22ad7e6994a666fa8d7d19397133730158327473052c1510ffacdeddd6fc7f0a9e1296a4d65857307f87391b6d5b4ed278a9ad814cefcf4f3f03ef033c76d64cc6d05d0744f5f71cd80852d2c6b5620490c0dede7acdaa443f51d7e10a7e95de9059815b7f9aa4999357956d1fb2c9a59c60c28fcb412e77bae13e6cd93b3a9acc3d1fd886048b0d697a164315f3bc329cc9203ee766e4516d2c5dd4971ed57546e3e91e1f072c9426c120cfdca45e055124b2adf9708312c8f7d423a9b0971417df0754b7c1053fc98ae48a98d888d5b815c7a8791be6c4022ec40e0de3efb42a9277ff7b0d672c954e20125592d251070c21d2e069f1f3f52be4317050d38d13befe342e265ab7da610653481007406466e27c322054f7345dd173a3536f4e847d2b97974730728506eacda01ca8ae831b8261491aa281e669dd3101a99e872a3b5a9ee8a81d7a9256089c6c69abf8bf0c67eaf050f9175c72cc0200727b37a13b30f772cdffa6bfa1fed1af54e44d141b5638e62080184f138c4cc3bf4dab5f7e8e85043ff70066ab390bd8af41d02a0cfc3d0ada62d43d771cfd9c557779b6e5c8ddc7d520c09de77ee81a3c3646c999c5755b54916a82313e998b4f1a9ec003ec3f08655d9060875bdc3c6dc477d818d9bb2b6bec4ced8e1273d878c93b334637f88c0cde0e6454d518ca0a3c0f1151d595b878ccf073f495476bcfe1e669dec00000000000000000000000000000000071319212930373b", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 24, - "comment": "signature that takes 2 iteration(s)", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "8243e3f28052056de7cc4b042fe1d959767644a1b000c5fc3cab98cd8d86670c2025a62784c13c5eb0f71b9546dae058ec5027d4e6ef29dd36e8ac6ba1dbea78cd5126919dec30e8bf50e9034aa5582d522bb97d30a7dbfb1af52d9cb655b7561a17a9df3d09b277849b0f4106cec822d715bc4dacea258f60f4b9adea3b394627b318d2f305dd612fa0826791b03c0a55f456ac9b8ddcbc67c88b6e07375e3aa5114a95afdc98e1167e7cb1c74bce4c835d1b47cd1be95356cf6abc3c9b36dcd2ce4b0267a1e0afc0cc9b7e3d0df7111efe0f936c79bb2ec2b3e65b0641373ba1096bd1006f19e0fda9c7d8082f5e09ae1673cbae86caf98cfe853a2edd27c48fffba468dd6808b0996cdc5eb50f7847f80e51f353ae9afc4a0008248901c25b5328dcae28617d3dcc9556f3e1bd86000e1630210bc8a6ca56d4f0bd61ec09b0ed6d4961cb56ff253039bc8f3b4f9e406ce7e408e8861e599ad05e238d214fface8605e3a3e2173d4b5e1456edced533cacf7135e0d212c4934982072a924074dd6ff9eb3985eaa4e108799c5609b936e2a0dcb32369ccf34766462dd2e310e561fbb09800719bdea3eff789b64b3602c2303286499cbf45cc769d8e955c2a0bc87e6dd60a94284fea121540966d1a8cb893695279771a12eb8b05e33cfe1ce5566337bf90dd241d9c31fb07c6205940b77f158a7250c5698d6c5c251e787bc81338f2171bbdeb3dfb29b2e9202c29365f33e18fe927ef0919482260c01b2fc94c90222ba4dcb14723dfbb3d6fce66da6eb6013bc455848e5c2e3f52f1bddc5596d4a5f18c8f9085b3f25b4d95f8497b818808e5628f94f03b4d838c013a3c2bae7498ed2f23449d77ce94069d2d1c50d12df6d8fb8c8f72b03bf04a3df67ce2990b56595fec781ecbedced215fc0d0b5e34c10819c242a122a4deeb607fb9d3dc68ead4ee07726082d132beb524ce9937b66ef218c221d77cee77ce255b5f18e7cd7c3e2ef9afe80c7bb6675128c90cf6b483d96bc6156f2b7a4d4c98097d2b3086519cacdc3bf35f8127cdd071136b889f1111c0db2953d4d47f8a9de23df6372d65e25b4f8887b4553ad11de8ffe01264ee810a5caac6cb214baf3ec4e5062bdeb0f892014e3551e1e8f5fa50defd5bbc7ec14839b1660d2b5afa5d67a945989f934205902b3c8d62a2190621c6fd3f47be0a69f68b61a5ed1b2c4ff03c7c22fb67a621a64889b1bdf1c27ca1c7322e6233d433cf9bf0ef2c3877bc9780fea6b1a7cc15af6d370e57ef36ddd0a612f1f7e25efdc7762c70c9cd925e545672ec8acdc77872745c7fee82c572d34c9341ba176a2f1e4e629bd1342d00d8bdbc12eaf17e3c2399057ff2a6ebc7834cc80f3ead92b86e0c9cd0a909eb074d97e7783074374454eeeee970e8aa7fe4c27eccc340adb62fc838fd23554554e62c0e4ee0a50a1f2cba806b6172dfca4e3943d4af28fc4e6beb054487d47f26d0d56b8c0f70393eba137c5f3c278438d264d35ff2225f4b8400ee97e550d7770637745cb7ca1cca4825cdcb9c9eedea9bccb9e7c9c2f43e5b95892422514890c465a4784ac10dfd3c3c5ecaeb4f74d7c7c1f41b2ef8a6e27879ce049054a3947e2f71a36c11f439af849bedddd2d4e23fa71857aaf34d8a082d034b3e6a438bd195e07c9d9a0d66a10a7c6a93bd9346314d8ba8ad5b2df800db47d38266b5052d82f7585ff57c9a4ab2f5c09f95b2e050b57e3135fc1b3832d86bde221baf6996c9a95e50984c7a2776a948f4ec98a21ee77507932e8da0fa1baaeeee4ccf34ee03f62bf3c267b3e02c327ec57c17e4cb2ef1be78e22c4090ec356c0c9d2b729b44e5d74d1583aa73de3d2187c910c5f30cb41586c014e1e44fa91c6155c646ead2f60e42017156326d8a4258addc65dc2fcf63d80c9d504d77222ce363b313bf396cffd8cfb802bf6c2f99e5e440fdbb374900b569a31f04e2ccbcaa29985e60c980b75dc8167e6526825005b07ee9dfe7df419ca5660315a5ddd47d70aa0a47e9e914f0160fccf4980a77a36fb78f02530dc01a88fc2e2be50d20f6066410671ad48bb65f4eee60b296abe47aa86967e454a4892c46d1b125fbf121c2972575de626b5b3320b419a58c844f6d0e4b4aa7308cffd4240aa4180f97b1241ff641d09c90bb40d4d4071f85b913a1a35421aac0be77db6c53e964537ca6ffd8795f21345b62d37a50a6544420f7142d54e6440864a0726172937974a12d775f69037266f501a9120fa31f71dbb64d562e11749260d4d3b3ddec8049199e0c34593dc34b7f5f51cdb963205ff57250d7bed8856deebceb18e8bec50dc74e9b3bfa359f43fdca881c9412fe5c791a7b0e0313300d6bd0b9b7177efffebb7aab23af990ca0fdea4957c2412ea51a7b72efc6be1aba08ed7bba5097be312b4cd3e684e47ef0aa96a5bc18da275bb9ef77f9ba05f4eb5fe1d8b88bfb7a8edfee8705dbe213005052d6c137ac399fb29c5c146bfb371a1f994f0b0563e5aa443167321318bb002434a79b2705aa24cfc36f7f748128bf7e38041a64cdc5459f2446ba34ce73959fe504587b5f5c2f91d2b5b9ded36724cf7f375cebc67dc5f3c5eb37a9d6095250c82d414544726e22392e9a7859898aacfdf18d2361f55139d32dd4786634ea2f59b0ea8db2f03ec335a3d8add4491c3377e3d5113b59e79360d816ec53834c8994ef04f634368d3d135aecaa1d54da5b63b606dac31c5969007e501360e60559e6f01c25a608724b13b978835b4cfcb69ca2deeb2d8b6235ebce9b0123ffad14c4cba462e47c54f7a5a93c5c8e1abe257e21ead4a6216a06aa454a15f8780c1632895dc497062048f04085e360918eaf7d800d4dc7b9907adb5a1efd1a982375792ea5c27d73bfb9f837dec8077cdbdcbadf95b02aacb8b88a725df65743db5a59348bbce2bd46a80bc9485aba23500f03890e8d114153bfd037a87d1ae27a7576d86bf435373d021c85a2a31cb1d978127f89fdcb7ecad2fef36de77ce19307e4ef1ad6fbf2c23224613868c184b318b77430c5e783ed0745c9b76e635fc808cbb62652baef12c848730893b7c6c3c713711f6d7819c8bbd126be7c743e66dfeef86b13ee6d74735edd1884badfa8dcad7107d86f841f69aeea05b28d75670696ee81fc34fa3a822b31a945141c56ae5154a56a04353e6a3c120d47ca11144d460005c75789e5251a225155d3655f6566dbbe26e248532ee4b5345c97b9eadb6f4bf629eca64d269eec8487efb7f7557052490d8fa144f5c0deadef6549cf5c167a02f208f2889d8cf9f380cea5960394ab163cad4b7a56dfdbc67be3f0e915ab030bc5018ac5f5a636b219aa00c077a22437d975689cee84b2b2555a3d5ff145ddf2a0e27b724265cd60c4db153e9975cd8ac5bb5658e5f61cddd821c31c349f770536be773ddf11b42d44fc22d5f954617b49a74e998459f230498e428927e875afe309779aca4bdab38eeb03fb8345b58ffac10a7b1e862e1fc9eb44def447a1e89ad707d36cd9d74f5f38a36251bdef3adc807ac384976b7c82133ff8d0ad5041116c428a45c9447934945def2f008aeac3477cafe3508392bcb5fd3db35a589f38c1b944e079aefbfadccc22061227936566c1b662c62d3816324582058dab11512eb1d6bbafac7cf7bbc4ff88801431ba5b14146fe27456e67fa285b81ebd34cf82fea2977dc70979b82f03d7e17815cf783b54e6e5096609653181c94dc8183c8b5561a8f8a3790f22c261ef3dcb7eb8c7a3eb0f432f016c92e0ee5084d121cfdd34b214bf7715de4dd6bba38d05a90806787cda65aa739d41d9511d7e0bdd9b6395f8b205be597590980a17f631d877a801c469f2e81fe6a44b915d89b04a3b35f087517be09cc2460af73d34b9c898ebe8dc48176316b3b747e1a8d6e0fd7d19753ca03b5c3ef1d0d9122e7c5fd373bbabec86da39fc3a223d3de048b2519fbd892634821dc195c011c078eddacde76fcc1a728906214e12be5901da2739751c2a5aed665b10a55b265e80c75e6d11e1d8ba9ae2e27fced1234b11ec8296eaafc0cbce4d65f1750a6fd82cd3fce774d66249d0d4e21272330cfbe89ab722ee78ea6ccc3113f6829e7d437b307b6eb0cec0082511ef8c69492ed46752523d5e4bbef2799eb76940f4035c101833f7059fa4c9c7765aa0d378c96982e47285aad8a2c5dc33303e2063166c10a8158f5e9e0b86fe152035d767be0dec7b4fc97313bd50c27bbd2323aee3d8b508a2fe395024cd8331996fed16f97ebf70ecbe997de5b8bb888ae8e522360097eed1c96fb2ad50af4a2a8961be88b46aecbcf31c573d5f172074f20e98d68be6129a1360a7c8dbc0dd74a21d936deb873d33e66f8d8f6ba73d8a05a473272b249025a8ad5740f7f37aa5661efe6558138d8487644ffc05f952777083ee67d180b80b1128a3a1b93dd3aee189f9eea635a49da7adfa127b7e2e5567e3e0d58efb6ae588d336bf38121e6f5494e66bc1a9e1f975d596468563f2af990bf08ec933016e9c50f086904f30ec130bf4a735d7b414d1726aa03222ccddef29b4ee69062e217928a00eb0dab678ecacd601ef33d6482e39bfcb04325289f7316d38938460e023ed12f38c38e08fdf6c75341909902408a5fe8786c25716683661f0060222db5d9a1188e9624d6eff0bbd3164adc28d6e09b339c0d825a6653503bf7251972f208cfdc0bdd1557f2f9892f3db0a9efc8409bf6c83b2e31bad172cb2dd95ae311d873bb80e642342814bb71890b5ac9e116f0f367bc85a790839e8dc1dd52b167f6abb3809ef2e8a34f6dde611aa4f75409f6c9e0bef4353d1c2c50df590130365e20204ffe392ee3438d644b8eea3f4a92c3184e232745957ffb88326b7846d4a64eda2cdd5b95412235e6420de10158930f675900f9b558867afbe6c182e37cbeb3625d88adf0dec9c8a3a096dca43b3c7e9eaa54384f4f987354407f2855f4ee5746ffcac55293d9187a668ec72c12468f588b7088b069b20aa03cd1ff3bd9af26e922922e327ba6a424eb0aa9180cb60da4c45a6b76aea03258818d9010ffb6ed4fd0e4453188513a15382e4e057708f4ef24d57d00968009c1022f3a40acca9dfa5523d7fd3e63603f198a5c72855e1b6169a333925fa5c4325efab41ca4800149dfdc8ce7635836978f797bdebf875294128f3ad72ed91ca8b52476f4c7e0c67082113d2dc327a4f6deee33bda8a7db96672b990614edcc7138cea1a006867ff22528f8eb7602720c58564cc8a9cff02b404355a03d60f03fa07cc74a6ba70dc4aa8f2122e5b7863af835ce5fa0e80ce1e62534615a240aadaf1e09f8d201559e19879f6f7715cc459229784bd67a3db8e6d65cf4b149b678a89661b3d0a2f22709347e28ba2bc4d4c408c7df1861266ae1fe47a32c22eea95164a42fdd9070e4403f5a8cf39bcff30f97b7dbbe54cfe09f1dde66f84be59754555e64af1d52508e59b97110440ae59da8cb70f2e7c551d3e41b281b80bead47668dcf8e7f1b2abc09af9af89f51c8690ac965aa2ef6ef565a532c7a0aba5520c41c1d365326a5d5e6f1b6796ccc828290e18a502c2fd403d915f96e01cf1936703ef01a781d7f48efde73d99e80f551768f1cab025f176cda4c9222a074426af4f94547b5108b89534344424f1985558111b570ca48955ed1035af01a507e93abb177447f778461a5908e5e1040b9ebae6d1d2f303cfb463d9784cffc3a95c6631b318ccd952ae9915c6de13374446cad492f84ecc36a4a95d520a76ada6a5437ee4719e73cf997b5a3a590a68356419888ddee7ba6db7288c36d5aef6030123bbf029f8ecb8302155d4160ff4c4c82cbc3f97b463791bbdd561431ca1fec380b31b5fcbdc920e634bd2b42eb8826d96b605a69c60c92a51359ab687b90b78ae6d94e51b64d721844b8b73a71fd1f201c41f2871e3a6e5d0b0e0050437938dc298f241974ae1c00e90e72e04c6ca294416c2ea243174076463b027addf5c423a93bbffa08893f9d401dd970ab0a907ecadde16a41bc95d492dfb8ad2d7ba7f96a98c30afe47011501608df033bf1d49b1b5135542ae8b0f6e556e0e49a9883e4632c6da8f6f4734e2754736280e0979faa883c5815033896644361363045923b8774b8aae0241f2ece112daf259ce072a1fb2c236913a52a9c2a9ad0b2e3a74a3c612a654f313b230673161bd54f9c0c907652a4a1e13677661fead894b893f8245525e6e39d43e5cef2f5686b07c94dfddf62d35f9c256df6c71ed2e4aed383cc6841b3ed6de8019ba6464c6db9c7c7156fe67b899745a65f0fe624b25a2763b7453233d522fd3a2073309ad4228452b84367d229831c86156df0e04aac208b9433c46d8fd03f252453505295ea122051b1c263e474d727815adbccded041f6f7c84cee34192dd0e252e33526f81cfd7db082728526497b3b7bef6ff2a42597f91c6d409415b77819aa8b9dcf000000000000000000000000000090e1518222d343e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 25, - "comment": "signature that takes 3 iteration(s)", - "msg": "0600000000000000000000000000000000000000000000000000000000000000", - "sig": "79c286ca136d6925f9a067a788db7cb507b741ede423f078aa1f9fdeebac927c3780d76e216664c61575ce121bdd42811fa0c6d39ee0bd05355526aba40288922eebbe167b761f1cf16e910f1f445983bc652f9a85e9a152c64c722092924244451fcffcb724b4cf7fb5a10da5a62545ca054e3ce27f9541ac5c5e9d85d562d948b3af4e38a08fab086bdd4f6115034f3955624b8303b988b4321aeb1a9588973ba54eee8a2972ce5b2c3dae3313a4bda7b4cfa336affa623da2a5968cef27f6c17bba7e29ffb32c072c694a931142580bb07c75ac2aea02bccceb200512d70ee02f82854181b5ec0ca8369a32a1749cc78e0a201e42c68568d511d835cd381a416f978824dcc0a360a2d5ebb724fb499dd56dbd334eccf2bd813945396243b5b0993f32e5aca0c3c6cab3dab9b8549fbfb193c6cd4b664bd312680ccc4f35e7ffb64dbbc406123af0a8e75bdcb4b8b4b696e3fb5aa738ccc5b8daeb9aa376bc62524436eb02504a9857244b5d06a8479a3c1ab452848fd2d14ccde0d8b59e8d1ead5aa9f68adc68a7b49a7f682589c7639d4836b954ca6945e24a348faa3e4a4adf62a806a3339cc5ae9b71a12855a4a567befdcf4f0a8cf30ee380464c2799b92a0d83e4c3ab8ef74a26aa0a9f5bd1f46ecb68d1ceb1776b08615142b2dcf8b2ff5623eeb985626295bfe59c7a23976d2230410267404d0a4c019775167111548ba3cb3de8dc341048f4359880d0a6d2f44893f9802dc461bf5d7f713589c35d141e0f6dbebd252bb09b738da1d86ae215b27ada192a1305946f9e4a169825cfea8cc0feb5b11a0d898729f6ef5a7d303357957c26f54531457c096fbf26c654b6fce28ccad4e08496267ee1e1a0c6a1d1a87896c110b6549fa0377533ad5295d2c6a28ded1836c517114f642033d25e6e1c3a143d71964b43d1559501f6bc47f51f6958751e726577373c868e63047f879902a6b4e3cd7a0d6da32895491dce6561393d89be6d04ecde0bc4ecdff098aa10d669c768bc029e9ecb07c3d5c34b61a83c1ea265fa47de7a2580ae9f65e3d793312d54865c5f0642cbf9b5bf0de2c851ee58f22e4d088321d35beb9ae1c16eae95ae1134691279974629b57f5b062807fe11c2d6e2a8aad6b74b760576e5ec5da252ddee496ecc99f90ee2f66d6420f5dbb0f71b4276e447a988f97f5da59cd361d82145556eedf01a1e595e2c5ba2f9f4082ee23f3580eefe907bacde9ba65749138f0f8d4e9439405e948c72050e9c540bc069a8da7d76ad414764de0f62af3d4cc9ccb1086e8cd927db52896d122ffa314ca889e18818b12b981d797dccd88d2e7682a32342c7297ca0942f4c6c07a80e3d2a4522110b4a902354b142ba6c3f1164f6d68331c6244be7759635c88f9bdd5b3836333d8dd9b9bb786818ca18d169155b06cf2282f985ffcd595666c8c294194293035ea4d8036718cf13d01e2e30b8f19af5e2e1bfbe9108e3800b95bf3cf2e42c1d1ccf35a82b557a3d2d8ec333b1270a54f918b501f0e794d7b7a9b85d39a4ebc1e3c18f201aeaef3a712d6b162cfd12d62db6673ac3c7188e97214e0deb7f0edbfe0b595c8cff011bcd7381ef4fadbb006a7832c69550aaf66b7850c475f86c2c09ba14180b48523902f8b6592b3e3aa5c9df2f7c9e31846ec331dd4b7d4b0200a20dce2042fbaf6d3047a1d4f1b78be75392a5f140747363b4a817bbc71e0eb6f36259f29aa2e60d7c3d12c03f52c0f8f0ea752024b4069da8dc8cad5a563a1d0005826771e32cd2a5c0c4ef4d51ba142092742fbc7f9fad1c9c5ffc47b6fbca46da333b33f2da1ee6a965cbd3943f9f9f1b85139938880a4a058a9a0fc3d6692228368bf1a469336603fa3ae7ea11fef3a50d1dd004a6004bb1f2f3118b5536be11f898ddc8d0d01ceefbe5e1da7a4abe0e782b5a5f1b797543baa1b0c984d1915dd449beb34a97037637aa8b7c8b25109ac3513423d01730eb5cedb5417f90ce559a526fc1904356ed48d0e016f29a7483f51bccde3382cb6a97411006fe3c9f65f3ee5d4ddafa852aeed447b096af56138158469514583cbc26629e8be2d219e51005e6d9ede30903a81198267f72827ad9f40512ded7d0b851230de5f60b8b9fa1867d3da33f3ad7aa6ffaecc77c41e2dc8b9bea1b385cc4af3fcd998e9fb43b318c453ea8a2265175cb48fffd3ebdd142f1e15be1458e504424e96fce49dce85eae5f059324adcf0e1c3cac2c1d3c4a6d43f7552efdd242c7a494a29ce68e52d8abe7d808ead1faccfb3ca5b54a194ed02371ffde4518b8cb7032e0d15473d1c5ec9e497e0229c7afd8434bb30fe9f5a94d9708db4f20a2d5834024259634190087d8df2bc94d279da0236b098657f2d3cf3b125d2926c450d8086de97e0b5217e6aee294bddd3d2bad63f74c3e9cca8a99ecd57811bdce2ab9a1fbd805cd7d87e6dad85f1018ea426ee9a9d901a6e2faeea62f96ee9a09fe0e9e5081f54bddf0f2fec5507ab3ab33f27b6feaca20e335645ace71a42f4528a2a15a9882dd7721973b05206fa1a3bcc0294ac00f6a55d7ad8d0a57ee55f94954361af4b3cd4e8623b0caa8cd623c1842ea0ec5457f7be6e84b46589260d4c9a8e4f68abbf9ac59609df4fa7deb5930b5a84c1d0c3c3bf6fb1b18591835838dbdd1c91cc7ab2d762627ef1cbde18690df1ff1a7e8d69b87bd0094524e159cf25204174ead33984cf01c79d0d45fa1705c3f19ee78e1760ddacd6441f51a1776cdf7e807f6624aac57366936d9d675acd46d520571c5b8ca798ea9d580d6c32459e37085b74ea9130b1857cd8293f166cf96286f8c3c37395193129b6fd7426fbe8f4ef50daaa210d9430c93bc9db9a5c006be33f8757b6a27be198b3de29c998acc51bfde26624fe17b45a26be1f22fa72984c0ae057f2e20610d4eda5f55a3dfbd966f71c6526529826c77ab4c1b2848b34d792c3665b5f5912416e5c7c92cf93be425b0d7cd15d5602de40793f0d81cb09fc0e8fabb311a13099761603bad67226ad095b5714102a8b6804d275c2cfa3b94111b3b0804688ff41a71688afe795f331bebfd5886e6bd2c4b43625830366e9779f0ab77bde2c5bb4530c87bdd03d39c0942e47c7b7835a556c0a819ab3b789d9174ddfc84af80c9f519b933898a8f1f688c02b051b9b8b8ca7f37974878903c361bd8b7af693a1bac0e9a310f10c173d6f7982df5b6b08c05330b4f05dd5c957bf99dd4b9d397d7c9121c7f2ab721d1d319481e5caeca66ea3cac8b4305d68ba8ecc058a4779cdfd2a0dff27cac748a2a0f5f6baffe113059cf3c314fd2417a5512e6d3fa3b882ceb0f1fc3da3f9c560b4070b79cb2872a95c9506732e435873eb629a3404aab2aa530deb74b04d9d933075985ba1a4c15c9ebda17b952c68642a7d76e963be939eed4ba550af0db137d12dd494ea3a98e81c233d20fb95c7d01200ae61072c572dd4f549152013558d0b86d45c65ebfc7d47baef0269ca497347b60bc7ab08c20673b06a14f71b6b6a85eb301e0296efc22a39ac3a9e37fd0cd3687b2cac00e409d9bcef62a56bacc4d06754df10f6adc32a530b7e536f3192eb3a70d0d2c2914aa6b115a4509807f31f2b2d753404df2099e69861c03a290fbbe958248f4be99aec97b8316ec9821c222bdd4033923da8001c0ce24797123258989e9198dd50a6847a91f8944168b5da4cd4158a0849a18b682f33e2e9e42a387009a217af21d6baf6afef3d8d1adece6ac3cf674a1f6a72cb4b6c6fbd321c59095bb62093298b3317badfe446725b15d405c7d23592377a04719027e80fef10419981ca4f2e413d03d0338bbe653fd86dec814a2723c117f59242ebd0eb6ae13bf44805fcde3f6f5d195f1eb9656104f301de3371977afa42b97c3f1cffd773c2215781cdfcc1ac70656540e0edeecbc7d4425de48ac9fb4913c397066308ef65d975179c3ad3b6d266cf2f5846370a8bd3a7619ffa4d678d5ccc5d020c4e672a39114e7ee68454a952e976dc7bafd9e69acb193033dfbadb38f7a0e96bd1db1ba3894094084915c6876c78d01057e01180617210c7e6e815d1a088052d8658e1625fa67c02928961a2ba3a1ab368bdbf070e9d87329f31c66d1a6416530c8b27b69609783d654d7f7d118c8980f069b19b1a18138c2a903f00f26887e8e140b5c74fbb316434aac5a0966873641dc30c4345334c265574a873637a648f98199f71ec99e7efa70a445e74c344c02e06641268da8ee58ff6b1f12f3c32d0b9553ce2a0051ee6bd549efe7a1eb4fa18324c023a1f70d2ff51a388db0ec81d718b66e472ef2454bf48c153299525b0365b6255a7d3ec97b3f4c33adc19d4be377749f68218f86c2913545d8d393f27d61a4f9fb764e9bd290347a88d522c671ef45883c348b4dd96c3120a268e528db74767674300319a1ab2c7bede13a122ca34d1e231d79c139a801abf5311319346ed84d75c6bf4c5ca29018350a39d32a15e1f917c89d5675286939f200ce095f9d58fcb6f876fc05ca0fcaef3f69f27cd70079271f4a0aba175a2a4048aa05fdb1e03b903b123a763b140098e75b273310863b68845bb75e92c35ee7bc5a604773ef4e5545041567b33797ceb87511d7e69c992b574fdbdaeb15a268e1d269588300fa45473a7d53082b94136b4129d96cfbb4c76f5937840d87f29a5b6dd790b452c0e97695582fa4594fec96d00fbada884872894f3181f7933c04747c3c1390ae24dadadc49625e9a44beaccc95bbbcd4cbaf4c1b6d95e74da8d2a4d22390a63158795b52e69550053d26f52243dc278428e0d4f8206a2541e0aaf97d653ee160caaa5efd7e777f9a1a73bb2aaadf7f0fd5bdd72b43990041f5775c77d958ef1c9f79357dffb28ea9dd0c6f3a97c265deff95aa0fcfc896d7078fcde2eb1453611998fff4c019e0b0b26bfbb7153aa51bb44081aeefa4cb175291b59f1b84c6392d31d3e1678c3bf3a6a2af74a2795226678f7a84a2bb88d5056a61a46c870a698e64aca67efe622033590b614e5b433c951cc151b87a114cb2a1ef993ed1d50361ba09c70501d8489e85de5bf78bc1cc00568e26d8323b5e0bf0f8b39eee8a7e2c8ec989ee674743692eab061cc76f62465d3c873bcf71c8632418a07507204f084e2342e2da69d8aacd14004f4fe9e0b41a797ba9a2f8fe4ebad4a5f272681d826f30419d2437ea5984358561793d73d5399bb22867f5d64447c088f259b630d92d6c1b21ebc6c77ea20121ae744b41a79bda368f532085729063d497ee9b3b547f1f600953993fe27d13444ec7180acd89c0823d18082cda09e59932881729ab6f726707543afeafa45d7fcb2d5ad15217c9edcb1f93c818f49f4fa5880c710e82251b571e89508081ecb7e3c69a47c49eb7770a53859e3171bc26d52b618ce1f177a2c6be4460d962832af11810c4f24e9a7e7d1658a5a607b17aed336d15a67068b821f4ff96569df7539ac94a32d5d59470d54d3674d35adca0a8a46142222de72d156abe9455f3a3f33baff961ee1d2a0c08d81c3105575279b19c1daedda6da79cc1b77e636315411fc6d001d1df93e668f47140da79507fd472bdde9c497eebad771a370ddd434779fd54c241bfeaec7721fa1c17a105b4bcde594cf04632fdb4af822040479684c5ffabe85cfda2f05f217c1ab83a64d3d4b51b7d86bb7b412b63924d6d8969f9e91e6c26e9f195d82ec99048083b935bdd8c5730bd3512fe305c290b9b6aa8ebc50e5b64db5b8f85f67396f98c9078efe0e3e4c643033c7a5a5d7801cec73b6fdf879112749e87a1cd8ca4ea1787e92cf69e1cb26b9d27e78829000be6c0f46f0a823a32bc259bd4195e4580243ffa5d3da1e5b2fac4112346dcf2367c5b4739e4f3823eab5d458801811e2adcecbd96f3a93c5580b3b58d1009aaa519c3dd017135b6650b6cca68c3ff5da5f782978be817325b184f8acac33658f3429c35604404f5adcc0cdd8e080d27479822f4d6633f6437861458f2d0b497bac78e7322cf97880f4f07c80d1216a36bf304550634b26b73d87a94c4f8223e7fcd777f6607ef1544d0621093deb17f57102d8967dc98b2d6bb7d149640b1301afc59eb0594d70b8ccf3efb84bb6c30ff3d0494ceb5c1af7ff9cfc0f4ac1f4702d1d292cef67510c660d1a4f21cc0b96e2da75c238334834b8aa6cc2b953226944a5fff9e118b47f29419703005f19e2b8f3e5bab2103fd930add4d2ed43881c85f796681d102f89703be0586895f1b3ba11250765de76e0cf701ef8316a7836378706f3a907b85db961c33fc76bdb6d12579b0b6478a1e38ef77ed99a45bd55879a5d95d66f22b3d79e472d956cf8c82a30ffde549f9932f23e63b818f892f36e9419a6eb1f2dd946a41d23a2f4928810377279d169b0bedff1fa737883a3dfff051c303e47607ea5e1ee3d5fa6a71e34536f95b7c5d3fa0f4fa2b1c5d3ed0f1736cee90000000000000000000000000000000000000000000000050b111b1f282f34", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 26, - "comment": "signature that takes 4 iteration(s)", - "msg": "0e00000000000000000000000000000000000000000000000000000000000000", - "sig": "bf6ce3f58a1472bae31d1239d024c217c1dc598ed246bd2b3593f424dc7c427a208c176995c969475ab18bf9722a62ff5beb0416da93941e55a7ef92a197b436f22f67af0c76fc71b8d9396c7955ed7a5066f3312f2232b207f3129fd932082709f221bfb78aca8b4da10782dc9a1ba7cb7cedf9b902bae4389af99c64c602e014b55383d9141599b30cdc3a82e16e837c36176d4fa08121d46dde43fa2f3064effd876cc20f88dc63354469a3073e111237b35d4a5858f4121d12c633d4308ec0c059843e81f43fb127b4883b0179a4355dcc65295206f4e3d289a615f7e56bf41abfb528171e5342a87fee4ec0f5e47821f4a9f777287cb9a69359cc04a4f627940b90a802647b05eb006363584149192ac1e5dd13f5a57066ee95354be3257e1c578b7866d96130e99755362c09f9fdaeb16fd4546b64d30fd72ba8ad18018a987faa72e3df4bec350c004b07357ec4d06725a6cb971ef3006f7e322e42038353b25ab95b73e5bd26046482099c25ba0b04eab289b00dbfe27c84a8889fae0c2ba2c44c31016c18b0b89750290b62324923069322760f60f4acb1c0724895c855f377fba9e2e951980bd477a67abd31b0ddef8c310b5aaba30422a67963fe30f7efd12324dfecc30c355b23186e5af970b82fd70ad7646f693b57f3dadfd2bf9562620b9746fe29552e7ad370955b3ded3e8d18d945dc52b24126c9192a61b821ee1addae29f0ca13ce78b50aed5bbdffe0f8c487389f2420a5aad4f44040cf356cfbfc92eebd7e1c1982fface2377d8e324cc639682d47db42cdd8baf28a12d5c58700093592a2c69d3e7fe0dad23b48a285d94ab9836c00e50ea45917122eafa5823e4601113dd5230ae14671b547f2c02a6c7ae4f6e88a8b5139db1a88365fd842dc0af6e4cd34d208cdeee251ea83c61ae953d2d843ab50cc29a780fdd9e7140be20fb7bfc007b074d89a2f35221105360d5e71679ffc4902f14db02c7e7c0ef9ac3f49351020e7eb52cf79437d9a43e6bbebf38213a77a68530fd73a9dda5af31f717a0c70f980d284f29260ef3417d816b6c3134aa713707d77acec76d9e28c298990d38317e6f688fc0ffecca921639085d1ca78cf6d416ea2a5e6c4a0f7b67fc101db7c82410617d38dba2a5247131dbabbf0140c1f030758cd7749e90623c550c0e6784c4ed432dfd645d5ed750912e6540bab994939dadc0de0c44dc1fb0c2b49c0940a0d2c38d0335750ca63a9c040e4083180a499e0387363e8b69e0ced57cd1c311b5c4fed5f1e84a8e780d2cdef661da1f3ee9fb89b6c5c20c9e9b36854d05073710e4179470e51339471a09c35d7daa74cac85de4dbac948618558b9532b5b2d6b51b63308dc68abb638d5b29db3c2c27a419ab3440adf080cdb3b0981c14e6b0cc33eff257d5cb30508f47ef8d118a99662abf0f9d5b40ed360159126f7b3cbe9612596895d915a01b0e3d6638fec77a75fd32a8f65310449617210d33906ddccec73ec47fc3beb53e3f77ec00ab4ea87930b4d1332b2fdcd5c56d0e9a6f309afd1ef913cb4dba30fa93122b2898e94d52b3313e24f78fb8a5a28c0844b9c77a3f3e0315f46a13c8a8fbbe7fb1b2e1319e897f82be0ff50924664f329ec2cdfef02a806bea36c85b0556db987c7508d6ceb35e666ff7a6135811d7116fdde9b2c369dedcfcb4569906a64ca2981aa810e33d5ce003e67d5e18366401df3f1b4fbcd5369ff4fbc466661f824e9c65ef26169b3a94318fca87419791fa6cae21426d45b0e31cf1ac2c51652952712c58f97ad2075fa42aa8fee67d8fea59d3c5274b9221b9757ad7fd5d5dc1ae4c3238aa6614986c13d795c79f772e070939798627f757698e42a143b6f1f6b15a7da4d78f52ecb7b28097d6b2f84a9de73565fd4e5cf9f88ac9d23047d39e9036d190eb1605e44041ca562e790c8df6d5faff3d3fd2e618a9c9fea1de414b6967eae0ce877d11ebea3c856dedde8376d4885c125c4d0378e90535fde59e32e8bb05abbf85571c5f8a7b0eca20ffcc9a88c0a3257c7ffa885150303eb5542d2048b9d2ac3c110d9c26b859c927ac676c6ea40f5a796de74bebc790543cd133039b29ffcf57b88dbd3aa433201db9e4fbcfaba39fcaad479cad7850e39c6d00d9d53c81b82c4f67ec9a5bbe56ff78e3959375bae084b59a180e9541a674d2c3b312797f6ad8b511793ce4eb7e59f74e53e917fbbb4e0f59a477ac4c01b0352e1ba777d087d34146b41ff78da39726ed86814cb6090781f2c716a0bdd86fa876e93476e64edf4b29b6ddd8e524daacd0ee96606d9a21d56a3c2fd68044c5a9d714734ab0093b1931c92389fdd34fb561af2c07705a69bd8065802f9beb3bfebf3907aeda2f3d0a28c46f909fdb7dbedd46862f655262646fa7a560899a0933ca27ffd2f4c0602fdd529b43de73e1b0417e4e209407f645e146e5dbe9b11826b4d92dda0de1a2de65990a913038ced80fa7da2536f7a9d067ab7f361ac745de1bda5e9082d8f32fdf12ab0a97b52931df6afa57ffad8d7969077950316e39aaa00af2742382581bab1f8da3a961f672c7cd356807d212c13bcf8a80b350706dd8b0d7b0b78082b63982e8ab1ec2e8f2cdf42754dbe088ba9fd3ff809bd8a34a7da4772cb7f152cfe5b77f04e5c07abe80bf9e4e0724b782f263ff3199efbea38340cabfcc1033b47d5b81df276770ee9fb4c2218cdf910b9c306b277eee1cd4af0ebff8bae8c036b5f5c819da5ace3447ea46423d77b1adf01bb5b9d0adae04f24e99e1704f01f116f5b9eef373db7dcc6876da2e3a041b48dc2e10671247a8a7d8f50734081fc92f615366e3c18dd5d5aa12fcc385c2b03b63f1ce078dc5591982472040aaee0ed6489ecba3a6a1cd9945fac774edaa2ffcd4b5b66bc7c937eca82caa4c9f18a08212b36e88c6fe751f2b495aff98d04be964ea5b441c6cd90162d07565c4f8f1c756721441241e687472b29658f197866815873a79d16ed6822f3fb8bd5669734d359810eb53eb1f8129157bb7e4d0bc6abf68f2d9b9529d37b073591cf3c8052b616e793cac4753b3fe60bd6ba37b821cc54bd604a8486520ef83fa8952020a13208a7b604cba452e4f9b85428e655c939458709e0904b31490db79c1d8dee0f7938f88a53b7b5067167fb1d38ad5c6ea674a8a930c9826af6d55f1ba7dbbd81257497404616cf17b0f648c8a0ed7bccdaa020a631b02a7a7dca3f9e2790f71efd37fb5c27f084fb818da6847ab298dac47cc20c9f650cb34d4f6361efea6411b4ec0c7f57bc5dbe481d90a1e41db10727df093d803d93c18bb164f8014040b5da0c34644279a54e241b046fc81a4a5b20fc47f835da085f81d8a1da441330e5f32507cb22ac0974e4db2d87266f4481b9a5cf2eb9ddf168f73333adcd3e4571187336c43c55a206fcd95e6a9923b97b4d17514d13d74bd38675eef6b6b605ab5f1f993d0936bb1406575a3e5830748aa033dc881ee046aafbf9c059caec512ed13fe2a0b287e2fea19aaeb70f126835327f036fd364258534172c45f5bec3143cf55669e3043015e573307c013ae0c2de55cb33a45a35d2d2f0c594f330557e61a9c166ac582d9caee3178731301aede8b7074acb4b6cc07f8906408a040a3ad6583a5fa7da84647390d5b2fe67ea35a2adfd42a05a9351b04086ffbcd62753f9f749deaa1754cddd7788444100b9fe91996e5988244aae4f91e223121fe8e581053cb2722867cc589049bfd395dc3238ff2c50efda7fb3293fd102362478cfdf11a2b8cea8dde7d4ad44d05a03f247bbff6e5e2ff35513a172f8e0d72ead022f0abb80a7b68e38456aae73b40f5a9654e6d84e1dbc876ed3185425d4452a1261d94a5bc566327a7ed28fabface3c576bd70152ef548d9449056e3aa95b592b1265454bbd8d732532a5c1fc97835b167fd195e86b0fe0664021d2ba2bb96ff20629d2d660b652d4e93d1f3a0dcfc6068bb262a77042c7a8c959b803a4b84ba919145c050935f442617c44e7aac4e3c6255819c40504498d2f18aac6419ee66f1aece5c12554cbb755ea7bfbfe33d05adf5bcf98708dbe0706f6876e3d9b2e75dacac91a881342df590bc519a622231a3073bd7471d8f766981579665c017fbeaac27efa19b5df439958cc2aaf39f12395de738439d99c0fcb534188b9b5d4ed86022ecea5db51c2e34072cc7e6ba62376b32e26110cb69512b302661d6e973b8967d20ba068fd07ca206e8ae38c50c80287a4439b6cb3e76fba9f25386ea301c68c9ce3a26d1075d842a07378554c366233de9d538977632e8e1b31b4af3c0f59df947049a6f8e571086327b795fc7c00bc580c2c2c35bd7a39f5b52afdb8b3f685483430781ef07996b5193ec574f05c68ef455a9c920e0d88068484ab8e0852057cefb725b5a2909cf6203be2c8acbab526188bf5e197caa4c7986d675b51f0ae5b2500d1f64c3a9338405a34bb3c16ef6e92cf8bac93a430045bcd2bcbff2d94728344a59ea2b5d3528c18c0dbbafcd72e9e8499ad427ac425ca1f4b2a01dd0849e81c953d4cae911077c748922f6011865c6cef3886b8734134370d9e409d3ee1f053a52976acf2feeda6d8cfc3383874c44268965aa6148a12f268fe395540f496341a62ce91c89cb6efa1ebdee85e5059bf0515aaa3ddf0fd01cc3726a27b5579d9f2f0b3d4e4fc68e674eac16580a339266761e9e794db64658c267ee189c2c53f7708c700f66671c4a420f2d0d63e77b1f2054bc418895f2c9eb4059cd4e48bb9fbadae1156af137746626cc7de1125baa289d4c34fb07a2fb2c784187cadef5470023200a50f39c948e4f707106345fc50ae16fb91313b62cc916ba89767b639ba3609ebd8b6aa1250958fcf850f770dd510836302e5316b5ba9fbe064b41b93cdadf8c3d380579e9c2547e98af83a314c697bf95292a807acff33bfd5eec1ffe0d9b0ef62f5ef4ab14bdea1acedabf306055dd374e5ca7244645da4d8697f7ee6909ff422c989791ee2d881e4972ea42e9cf4349c94740cdf41f00866cfe16a934ab6a9ce8228117baad1c6bbabc2736baa46bc48cc52b35bd31d968b14eccaf5339984de9ebe22d19c458a7fd63d28cec45bca27710f29037f7e3b6eab447a721db418e10e7b57f103275c1aaf601efe93545969ad8463c16c645695284b7def184c340bcf13f9026876964af191e875a567878b280a153cb54afadc3aba5cde273783cc9f236022ed6f055076aeff277eee882168a24137d737840221ee0a39460e3a1ec0caa07d42028e0f210290d4205faddb7854f4ae7700e3c38327c0e8b8012fe86617e1cc5cc6ec45610ccde94df8fea1c42aff1542ea77aad34b82c602ad32fb2283f1beaa21936d3f6febcd9cbfd591346eb3a65bcce17343bc2aefbee3bb211e57d9eb7f27910716548eeba130b15a1a350f35ff9ca364e4ff1d3d3b9411d78da9014ac13996c0887478ad7b6fe918e23d1b184bf3cf4753c0a075ca24220d3fcf33b8d7b4731737f32db9387343fd1802b60bcd6ff5ffad78cbda063a5cff557138065704c54b8dde9948e5042e7a9399e0f2117e4985791e43bd906dcf2359756893e847599ecf5a0ca6b440128934e19480831e82ed53cd15466809ad6653506cc2ae47494c3bb7ea8683a60f3091571ddf8cdaab3009bd9f2f232a4e99ccb598d6dbf77e10adedb7cd0108f378d4b165edd3d06c9d92732940ca584eefc2f8c0b0f19338ff0b4c6d771e2637524c6d6576ae0ea8fd5c02a9245345adbdc155e603f3e3d35bd9e90fa360adbd013d5732b922d847eaf0ea273dfc2b0636909ae671206419c31693f809898fda2c31049469828916a01839242098701eac7c37b93d7c293b91b5b64aab87f9df78cb8219a18fa2eea18072624621ba7f2497e7dd101a6a7b51fa0d06b35787b1b6df93c98aa88b59ee84e565111120c8437c1829ea04c1343387da7aea0a097dc6accfc9336096c48af0b0d56f6216b10b38a0dfd9f66fcb1089708647d2682c719a2e5f3e2df3871b500ab7b04428623d0f605bca2a67ade08bad957a96310d0d96235f80b8169978928f43c535a6b4bbad86303e98a6cff381917a9c56e8f12dc11e3896d732e55f57682dc110b43f85e2b0e48c0f575adfb3452d79ba94ed3cc53d6417595a1c5fecb5eee3642fcd4433e0bd1176df9437bf7eb5ca45efa32c00fd40986336cabb91e7e7ab004968377f2e63a50734edab8fa97fbd09c2a61d0e2bf6572114c6308dc03b98ca96cb5faa600f7330d9938489b5e72f765d7d79a1b4ce40726097d30c11fb7b8963de88ebe1e943d71c09d866d2891fa8ab9f49584ab58e573049039d152b1289a5befe44cc8b5a5cc42a9e00c673ceea25ebd194046c2ac3216e54a0117e8d9899bc084a620b2468a0b6d603262f3363a1d3d7dd000b4c53567a97a9d8eb033e668385a3b0b9d9e1f701204d66cf04156389a6d6d7edfd000000000000000000000000000000000005080e17212c313a", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 27, - "comment": "signature that takes 5 iteration(s)", - "msg": "0300000000000000000000000000000000000000000000000000000000000000", - "sig": "4f05ebe543bc390942447d1dbe184fab96b14d92cc1f096092026f2a535a3c7e92b4d198f65be958e7da21797b68aad233a59fa05ecc76e22974272aa9862e92aa4f3bc7c1695c510169f6177a574c798a4308a9055b0df966b15fd75f9de02fe4290d50ed814244764579fb9fc6c50459a92c70daf58574086feeb2c24f290b7ba99bd7c5198a018d157fb21ba42e83d2ded7ae6eaa2cb09866cdc83f666e09983aff29b8fa531a008eabd84b755a3052004e3bca4477650c48cc46f76fae4a982675148bb26b4e8842989af547d8d394755b3cb61d4a1672ba9b47bf5b65553fa358c1d042928ed7e5e66c71dbcfd611ff2c55879da2c5f96256f9781301befbeb8f94f1bd1314808cdaf11c93c138ab777d8ba038c7f7cc72f1cbed2ba299732299cd87f35bfef8e816bbce3860f8ea529f7066360952de182a8639993285db44b5cc5db2156d6c9296757711c0c0e989693a625b8689163d4e3d3d60892888185279ca0ee4760472553b74d23b6afc9cdf10f180d62081e68052daffadff5ccb9c14f2f5f9725b21a593b83f2f461bbc1edfcaabd20a5e1b6561d304b2531f0d0a98741662ef8ee2e16943ff6c10eb23c228e7d0fdbe026a07bc4a8d933e08b9d092cb6bc88cac343d93f3126dcec3f0f8ab118618c16c0fb3c95f07f7f6f4c98752b2bd60c583ece4dbf247f466cd9c47a9848429b9302482d5b9e41dd5450a9d9c0ce7483fb04baf196db75b258eb4bfaa5c3008a419bed93bf8d914e10d8210dc47e4804adc8131ea62bacf407eda0cb0636b69c96ab4ffb66953e0a3a86e826f2b874774c938af5cdfe0efaee113cfd986749422780b6756b8f401bd216d645d5e9aa71ae39d4f725922625a58a784a133aa32727026d270d54271bb26bc6e73965f0587190262c58c5dd35a932594fe6cf4e77df95b540259e4e41577689db7b1fd12222908ef10eb46d78b1fff4e3720265cbe4d2147341342593042f171c8dd4b081a95e4ba44d124e681f660e853b54b2d10b4d809e5ceaadfa365caba753702aeae196fbe16350099807d1b71fea2dce691747e66ae817c1b2cf5e3c52cd461d00179411cc9f63eea93b02b2e9d0077f6bbc046f8e62f35283a706c33c5de723c6bdbdec4ef06f81ecda49cb0acf4f556305e9d5d1ef3a9cf4c45ef9c18615bf22ffee9d9b572ecf05815c09293a4eb14bfcca121fff08bf0f2bfeb7ae8a80aca29145f27cdecee45ef1adcf1d8aad1ef1e8877d4489fceaccd6565fe43933ac12ff5b04f89c0767fc53d9e53750bb6234898ac6b534553b946e10f9e0b0bc6443bd46b92163666213a065e7d781551dddc78d53612e000ad167ab2c3a217335fec14d82ba6ef7339e2ec9297ee17a1fceb85be2d558c33c569a61af447ae5aac261fc491c928160a092fd28748959878535ebafed74f78ff2fe44c2a0f4a4a791df80b9f98774ac148e19f3a39cccafa1b8a27eb24307f1949a115fba67be21bb17dba8353d9276fce0a5cdc4b902737db76ce109cf001c812f6460e319254188f09a663c2c4e8c2a66439f1c6cd208f8d581097f66b193e7e094ed9f81682a05f13b3d5f686db3a546abed7f81b9299c852af75af452ec465aeeef9467c0954a400600d1f47b702cd2b961f2746b2418f967e34f56d73065b6bfb27b6986aa01a5ba9d37737d884d254a5835fb56a25317ec8d0774a36d2354fbfee1eb58f656f05d49f9c7706067ff8de4f7a0d5f9bce3dc24e18b3368e9ff31b1a8fe8b96e05990a5398f28f307408d3216fb73b281db8a96c56ece65e8702a2b725705cee64c83d6cdde26ec562f2398a9178c0e3fb4186894d8120e0c9eac27c90548b7a220a24c7fe725ce956cad944feb8d6e310e01b58eeb29f3e8d2ac77b922ebdee625a9349432a97a749bc8de2138d1e353089972920e2dd505b2f050b154b2871375d8c0c5644bee8695e071829341145a57e35bfc6a703d452cc05070222f525ae6bd1c31597dcf8c60ddee4c24029781273e136f8c111107c586e523fed7eaf10b6d697fef5b60bb921be53bd33a50d9e1f082eaaea7afd6c4a372e720d092a85b4c824b2ecfeb37b1304ad4de2b89e6e57f1d03586ce328592850f793174b81e3e5a3eba483907160106f75f56ec6e3a9dc0fb5c737710b2757b77e581f25687b4bfd4393d6e1d93045815bae692c794c4c7d641f9a63f9a1dc001c3c23e48b276ba957026aa77f8ebe636df1083e88d5124f5adc6ab96a7eb76f8fda454867f7dec7b19ea52f1a9de5a4f1710960f4d991fd2593df95fc5805754c4f26d1ec55202b30eeff6801d17022fe4feaebf062218d0d23d2e21878edd1086b8c15c6c4bde37dd51e950fe4532ddfa1462651473ecd36d1b11baf32f3631b07c32e1dae061d5b6218a43df9a9c8b0de5d6b3bf1d45d796dd85091a7d67fdac72016a911bcf65db6590334144a9adebff5428f3ad6d11f5c9e470244a15e5d4ef602eb7c514b603934ccd6b89b39eaf44f3210df1e276ba0d345eb77ce2e23096177464080b0a30c7c35dbdbe7bbad66699cb31cc5a8ef2797bdbe193af65ac28a083038d291feca3ef01859357fcd33a09c571d6ffbcca6d0d7a34c1c6690e926c89c29b8bdf5bb35c5086d45a485b52fa45eb8ac011b12f2c07b80230aceee0edb3c8b7f739998e25472438ce90f97ee691bef878c9e943801a845abe3653300b7112e7c8e8c47a666b4c853c3e6a8d972cec32746a77e69e2dcefb60619f77c6311d5360737893c5ded1d39b0335a75be8ce82ffd68572f9800f44d2066a4ff31f47d831a0dd740f94871795112becf6326ecb0212e682da81dd24aefac14fdaaf79328d4a1db1e8f8e32886bcc28bcee0906dea4e609e3294a82710f84a65f8a3347081ab162ade3d9feb4389d5633cf0a11c25dd921ebbe44e41e316c59bfe2d85fe11f47499982027b275ae6064794421c27bc48956124cd59125573e0922586b9d7b45410d59b69aeac0616b45d4c926207a351dd47b538453f62833f72caf989909590f974725bb8d6b28d0a2f2849c9b67490431f2369bbd9c82e952b2f52d10a394597357abb0ae2dc362aced8dbb7c656009392f49e3dc4b39b69ec0636cebd80dbfda14a13f1ff0a667665ce06c7cef2cf7b6fb76d559dff4b4c9bfc7342a368846c696055b04852172a84c34709919b20d7d1c26ca9c5a0078adf4140a308c9854d3db58d3f754cecd19eb38175c622f315bd4b06fbe95ef58fc285bfc32c8c7c3eb108d9c2a1414cf0fa7c29f3f0aba4dea7f0d52aeb6801884daa7110426afe86b92d5a6ea6434efb5e4a3426188cdc4d7abe93165f759d2c1e133c2300e8723a4838f00f7b767dfd46a833dbb18f11e6c6f46dc60bda9a0ddc542d88dcd6141fb5bd6288d444c668b11ef0d5060a684e76665dd920b6b62f8aaaef2577773be5b8b1b0a6bdd020be3d90ddad1923c73ece562104aa1ba190714d89e390c1d862b4639d20805e72796d5ca5cf3acb3d1e1482c91ede1fafa3de0a17aa3fc2aebe7d548a754ddc21b2c20bb1edaede1f7d9135b341248560d20ad062aff33bf7cc805fb965615df40b8888a16e0010c3ea374a5bf854954ce2aa970a78a477ce877e1476ee7e9bcf4c053d436cf8cfe4a19ed11c0f85b110e68a6bc9d0dad3ce5fdfa4b70b7647fadec9fdff273d29a8b984792ca069546c1a30edbefadddfb507b106b3e2980909fecde27ef544be67d8f110375a3b7e83e8e743f58b8ee59f379314b3982dce9e055581a5a58dd89320be4d8f70306b6f14c0105872e1f68c2a758ec2b77845d34df375dd32ab5302ec4e497eeb58e11cd4878f583a2e98b27e4cab411e25b9c7152bb8b4adb09b6a993161cbfaf66334b59391927e5f39174dd1661495a6b702fa51050e5df41570e1ea5d773fc3827949aca9c3d625a616b700664e91cd6599dd40c19f8eb4c2023422aa6d87f3d1a75696b6f6430c602ccfae5963e57bc9abf36ecdf6e51c938b60589ada1bc1d40717717694d0123740eaf23c47197b6408c3be82d120bedb199b499f3ca34b180622a86431f1979059fc1f41ad7a3b3da1eee015f59bee059ebaad20f194273bae59e41c1f3476f4e15b74d2600832b9474d64bc716c7f152660c80297997d0b53f9dc962a9bf5633efd8cfcbaf32703ae121b0ba85d1e67efaf708c5cc3f2cbaf6119c41044dd1469933a9b94aebf82e2f97e854211745daa750e46934a4585b4c86d531b572b459dae2dc3c2631a1ed5de6a7ca1f7da7ee4cbb9f198b9eb965cf556a899b4c770bf46ce17ede41b5c897e67733954913fb83f9d88e10504fa858433df6fe3197bc9dae7a960d2cff6b7e67467788288253df8bcef61698fe54ab860f63a8b91b238ff904a579d53b57ae887a09c99d6904d3d1fe02a54149235e1a4d562ac008b607ddd0137480634bf2091f6c87f9f4073522c0ab43552df29ad21db0bfd6a3445505196af559fd6642e1297e0ccb20d6c34611265a06f9282738ec6cacbb73f00f3465e584d48aada9d40da8b9c84d1211cbe94a4b0eaa2aab07609585a4b486a5b116a649e5417b299e609e5e085a5b0a91797545cc9df523e55f3600891f36536bbaaa258df68662a43a5935a4dcf0c9b9fcf47cf296150795457a6b7bc820dc14929a81088ddfece65b33696f666af613e1ddc21c79499fb0253fcb35c7dbd7590818cea8a0f395bb79da2b46d3685edaf43cc6c5bde5884d46bd78f4e75eb315096d9f603b49f7507941abb3ae92cc7ca3854b38e3f5ac5af4782a2ab8949fd7e705e33cc652286fcd3c3d6b37b0db52941dda3244d7fe5ec571782976fed7088dc45f87227442db882a8cae944dab1775cbb33e6ba26a09b831d33e4b01357a41e2aecb73bc543148bfb659ce4716cbb8fa246cc583cb045390162f07fd7771a3026894cfa30f3cc2c61fb69fda2afeb20f034637c94976177fb5e35a7b3d8d3fb62ed2a3a5a4914cfbea446bedf93cb332fa38ca09862651c3416e8b646628e331bebb4ae8e4d5b965f393f9665ca82429fb2034da62049759c6c47a977a3cdff7faafdef74e4793a985d5d40e33e164366ba4070ac3967e231cc5102d08d4f68e9e3fce936fd82b7329c23d273e169224e891a0b058d61496688233b740aed515178c4444539927711699366d97e0a01d80ea6a099ce7212b3c7836c601b87ed5bb72a0a4a4c10ea0ccc7b3564f6623d42a83557846c3d23e75afa5bb4da6f3b71f522e9426d3be36786bd0a8583e1e70fd483736de1cb7730a20b1bf2a6f652bc85ab128368bb588c54812082ce8bcc8c982ed592b4c5f764986b249236f184b885cb4636efa57fff8a0811d611cf1e129f047acb841462111c8e65162bad03eafe85425212bb46321ab3e8e0a1b507dd5aef11a4f5875ed33e027615faf36ab09a12093cb43df8fbc5528c988fc4e1fb7d31dc8584a41f75096b1eb015eaa3b780d62dea11bd166bf8bf2af5ad1bb3bfbe178cf91edd9edd32a9976e3b085ed115d97b3db3816993679e4e7cae55914e4f4ac576bec628ffdb26213ff8a8205046fc91e042e803a88c70b14429c2f7efbe3df858dbf497413a84be372bd58b19e8f3c30a73747e2c8e1cd56c81a25f1e36f914c8c87d565bd6c369ee2bc4dc99fa0984270c5d4cdc0368e330e37028b43e59d2441462bfe3adba3999906bb0c5c3f5c1a55c689a8575c2acc5e443298f23a8a3d5f666540f77e4ca25c399a9f34878413ef03643b74f84f4553c76a7b253f5f9939b0410e899acc9013d0b799ae4e2962de2f35fbf1058a654c7d03f011a3ac3855940f1f060cc239970b3bd7d94d7371eafc1b3c05b98706828f20c98e0f1dde697652d0670d1de1ee48db07522ff1b8f5f53089e6fa2c5cf62872f202bd2d14882a0c24f2fe3e2605ba785d1b2c2b0230ab2f7e070eb6e82343cf9f1094c6240094d846fc5cc4bbb561ce4d27e8771148e19d8bf858767f3c262b4ceead4ccaeee7f2933bc888d2e00a6cab1cbc5bca6c132c1d221add24369f8b8ca903c50aee9922aa3e2d17d1f9b62025d338a5131fa6c0e351c309b0f503d7d48829fb04945b5474bf39103a3761f4e85eefea521d027c01fe0371a9ee1b8a128021bb7b5944580d8a05f4ebf1f65cf47a6e8923555f7bbf22eaf8eba7ec1210a32a411c7cc68b07bb3dc29f89035239ae24147300b50a6ecc37349097ffa16a03bd51fd40918175807a02aa9c41df0842f8b536c9ae843b05135cffa16126201e0db76a1aca2e05171a5f3104f723c4890e121377fb716ca40cbd82595854f1a244b4ed47e1053a79c344f79e766493d7a4db8810c67653db3581775af98a8fdb8beb50e866baa6e66bcfe188601fa3d25932eeebdfd3c00f1619b2e850c92d589bbbc49199d1e815424380c0f5f93f647275afb6d9ef00295871a9f848b4c9d7dd3b7577a0aac6d2e0e8050e324a9aa1e8000000000000000000000000000000000000000000000000000003070e161c212a31", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 28, - "comment": "signature that takes 6 iteration(s)", - "msg": "1900000000000000000000000000000000000000000000000000000000000000", - "sig": "dd370035aa98f42b2b57faf39afd86b177063d9eb141e653796ba22cafe2bb78378ec040f4aef1642e3b41d421712cbb3b5f94c5849e111ca7606edb34644cbc4e606e766f4478f1be39cf5d4999fc79a35b90e4479b2d076e5fedc7e37ec0bac7c8057c3f776e9a6603ca9b565c7a06b501db4a127bcee02472653766fcd200561fea3f3d77abf6ccc308f6bc7b86d9234d6bce06b1ce14ddc40322555f1ff06678bf6bee9ac7b4ec53cede236f322e0ba0ecb09e8a008b0f590eca532e441dd19fe6fc796ac48db363a8a4a90f52237330b320e55ee8b87a7fc60e1fb260e45765c840ebba4ff4e5f4b5b98b299b0b7a1478c66695201d1afbbd1ff45645ffd9e55e1a30e5f3979dcec7160cecd2201c90d707162cdd95c37d20e9946b9580f1e81af2ee6a8746ca6b70968c2d4851d6d04edeb301612531d0a25a5aa140a95d54ceb8a0510e406063d218813e99ab439496d80198a02f52a7ba78e8a15487e25fe0d5e8dd408eb56d058599d40f536bcc3b945bf1006e785948c57d78a79046f4dfdb5f266e8aa2e3a4c6225484f8f9baf0decf4757055cadd1fa7ae3c757b0453747c8c68fd5e2b978748100870c75ead2099e3a04b3e3dec5cc0548c1f9c16407651958bb9644ed5c581407d8b72a86afc6fa7f61b657b09979b125a94bcb3fa118e69110df8e778898b2083d16ad64373d69f785a32b92cf0c0b29526b0477350af63f5a28f3c48b08bb1651367baa2f85e0825acc3af9206810876dda12a14c48c22e23117977935aff0426623831b3b67fe9498838403a9f6d07584b7f4ef930d89d8c5ce178dbdde82bb84189857b3d1e21e10091adcf600e2d9f2337a4bd3f556bbe4b4efa8bf7ea5127020949d8df149e52b8e43a8b6c529db5bec5cfc1589990c13fbe3ab5285783ba451285353f2d5a484f62b313b87f6af781621aba8fda91b160ce034791334ecb35362070edcafa2e11a67c3ab7ba3a96235cbea35fbbeb6362ee312cf0706d973e6dc7fe4ec4716d91db6b6f84f612c5bc07f23afde3d524fe2b994652bd8104de7346178e7bf3ea0d889ba3284137c848dfb9f5659c336f040ce646648d53feacfcd4368c74909d74fff85c789d6e289ccb84b9d3ec4179a23c3154a29fdc467f80fd4efea66b6cef785430943bd46dc11fa7f23da810bf79cb1e5f2743de611ae13a3bd26ae14b9633095304dce56e398b95d0ba16b364b0cdbaf1cebe9474e1f3884e70fad71a0993ae47bf733e8984d9835e901b57952e0409c53309b5555efe156573ed6f083061d9c627bfb217e7aa1d63a650cf7dac2440313864521d9f51e0a9e75c32d7b122299b44cf2d96300918c2aa8c37d3364760f3836585bf46317e6c6ecd111db7e2283ad49918b096578735d7d3db1e6c0085ed70027288fd6166aebb5277b8e992a0c4b1f288e9b873a2a8ace8d628e25eb6955c256331b3d3b86d9aaae080ea12db5a12bc9542995df859b4c05730940ac9672c89cd31729d32ab01af6e2da497f17a7741cf6685994a993681165b3cc8e472ce4932463cdaf25314a5fd2eeb42e60303f9f62caa848b680a6401c8e46781f70a3e113ac9b6be4c86cfd86de94867fc76810cda3732b41a69ad8de27dfc697769a223b82516ceed8a4417877da596bcd432c0c6a61ab3c346e1851b9e8b84bb3be80d3c6cf09e5735bf2ef2308464d4229ce660ed0cc42b8571a506b53785a10ecf86c51067aa32ffa4426302621797cf91e11f8d3f3a72edc5393a7a009755cd7e542472847e65332268d6150148a0aea7cde5b39b17afb031283d466f3ba17579b14a8e7500ffb87d187b71fae8ae1463d2bbb7982f97a4e864b712dd71edc687b348442bb1abd10d879ca99ba9ef43c11b40bb1a5de2614d66a13bc53185b3243a8d5308f78aa388cb750f54c0df7892a7face74a0340edd041ebdab40f7ff28bc0e110c9b2692fc3cbbd8886535348ae74d128e83cc31e02792a96bbd6265bb476d0f379236768325aefff7afc20dc49eb9a5913ea7072e1312145621c5e9cc0754c5f9d339a5664abec1c24753371f545f8c13f1ec229ac525e9cdaa5352410214a97aae60d4320a79d6776a35c621cfb2392f621b042a9452e78f148968698fe4ed8099f5863dc4b64d9c4573e6fba2ab509b39b4579cfd0e6c0b8f7d68b56d1bc6ffa581a21a0785090e785e1bcbdf5e772030e73c794b1bd45f2346e6cf4a1900a1df7854f2d3141e627f26e113852f4d05ee37d38f1aeb0374474093da17d08491e0bbaf97a49674177dc568538156b67e6867ec813c6a60a5a1e6c1388365d1cb94cf854be9364be2590874cf49d32a9c73208791ce96ddeffca316fb945017f0fe30525458ea5666d057099a60dbc583f177e820927e719da93ebc5ff3f14896fc4ae1a5ec5914d46483ed44cb5601290f16c49f5bfe16ea018701a965c002e2ce904ed31925c75a7b61212a276cf95b947ac94ac00420db30779996d793c266b7234f4a4ccd7e6b12815a63aad41db5c105eb1a449c0201601ca1d594cfba16025b066ce0757663b3ce0ad7ab49c84946483547b7f2c3b1d1e5bff4c5738b023686e888628bcbd710a9a62ce0e199c0424906f1eab3ea74417860cf42452af0c722d9ffeb6dc6a0071c5333bc3b3e51638c76a9e73197da8ef57f12d4a7de315ea9ce2c387d1f3260324c3b39b8e3eb1175fb7526fd4bc00839593ddb8af32f5cc96ea23641d0786bf30f144512a7aa868df8cffcb70b2c61e6501ab92147ddc35e8f1cac0c2a024aac4153f3aa76fbd12c93a4b0ebf61ac1457b946859bfd2742d63dfffcc527259bcd381302d709958b2be30dff7d4b9e9aad7e4209737e23239e3648fc37f4eba81c55aa79222ab2e396568fd812c9fb100cb6f0c1fc9478e90009e10aefa5f5bef7883f3d7ca8060addf254ce1362186be271c56b2deb82b297ddeb3d80797d7e57aef2c4291028941429004c93c700597f935d4949b3133df68a8d17545385446547c85fb59b6b8068423bffe8ebef2d2c237eb0f840da35aa45d38ec211f11afcee53ca9b39c75ae381e345cf401874e464927d83540835858c77e477d3c21b24aecbda8eb441a2eecf035cadeb69aac4bb0b6582b714059e67bc243f881e64c5c79a1fff9d515574c21a756878398e7654dc4754f749c9c55d7b374360a1ef224faf3cc91f95fa95b988edaa517a7106eaa28eec362848d462a1701a3e13297967c643257c5938fe1eb5bf9652fd838ca751f19827ebb8910d69278faaf82d5856555c9f54c45c0a816b348e5a51a3904556a87e189a1956f7899ecec9c57278ca4c46eefc42c8f9739e0cd5e28c4aa35ba72efaa92b7e2de14293de13114aef9741ebea6987e7e351e5f1d8af2cb1abaf8e59e826d061d3c09e3ff133f35caa30d23393abe84610b42fb950906c1c553ef4bd72bd3f06928285531d18a640391b34b79af33421b0ff33bd770bd510d38432850d57a493123578ad6532c9cdb12b6cdf63efe06c082a940d226897e8f12b22d9d0dd44413bc1904a1e8c4d22cf141c07dcbfc19080f13ddea8b02b61f765f20379cc2dedbb13b7b6c1ffcc40e4ac8a70ec3165951c8a67b9f42ad68b66c653073e427341e391f44711e035cf52a19b8aaaca16c05193994e99abd358515d9deb3b257ee50fae801fc3d250e84fe0d74db7b264237d4399f97ce97b3ef48b0a6e207a845b541d0dad400baad733ffa1e7c0acbc7fb58069421b4e90915601654868e9b5eaba6fcda048611b0b4dd1476b6414e5ff7c77ccc9448b3b5f724c37e8f3aa0e5fabc7faad7a119fb20d77dcf2ad0af781e60bdf5c818d45d948cff31d0f2db3aa7db39b9ac67d916b0aab6945410535167ebc664c3f5126aebceaea98b5a453ad124b1198dc33c095a7d6d9eec4da14235dd4e9d2bf79b4479c86218a39574e2c1b0e5dc92091d6237408fddb7e30c5b074c165d056fd0de0564566baee28a1bf9a7a5635ffedcee0e2ddfc56ad32d943e4f39fb789b4bd1454df62746322088d57e552448b0459030f44bfe27104b9dbed4a3767486042b098521982d03f8949ea96fc1fa4b78977fdce9eff19b8bbd8a6b3ac74afd6b377f59fe8757d99aecd1b2db07b2b8c1adc83d8061e1b46caeb062ca01c3f4e76e782ad23b1824eef9ce011e536b2b23fcf7423aab5a3dcaaafbccc6337624eb5a859803c31ea714f94ae2a4ffe7c08968932cd634bf681ef1202addce5c02e6ba34764c6e5c78265a0940e073fd241211501a38273089d3baf8214b063602775871d5cd7dc744170bab3e05f0f492357f88b7710e5a772147b1550ce97e22d1031f6c8f6ad1e12ae1d467b7a9cc08562b7ff21e7b452d20509ade857bc143e17f4b1154489cb9539f5b2f235421b51a1b72e7344cdc6e4a2c8d68eda01e4ac4051c857220ce3124020e513a92700ee3c4f00e85e0eb95681303685878906e6b1d4d480049f4389f3dc1b41b6fb7bea59ed18bdd2450249d5eca8d3f9183d7bac3163756627db28d8e4c1a7698e63f8c350504b8184bae970e3618192a96fd0b81a49640245dae366d146c71cfb8d1d4efe4ff6dc2aac2f2213cf77f92acf7d3c4a5fbb1cd353aa68a9bc376610d6083d68c137aba09338bea4b5bda4a1946f22e322b8fd9167e31ef83794b3d612c17a9af71031b79689b677cda33802e3c6a6c10cc259628bbb075e4a50828d117d2643babe4175178293ef6b88b5cf0c19d576c4c309c7ba762e551b98b03871b9be56f88296f043bfadb0ae40d88bdb4615466217cce78239d4b5e258fc3bd22678e467e833eb9a4e0bd23d999d74485cc03249bf2bfc881f823c56fcec40d930d6d18be3d7e16b01cab1d054155e4e547fbb380fd148578c74f42a33307817d356a5dc9bef3898008be3585bec27d21858d48ba44d5f88a01f886b79715068270b692e8a32938dcf5f49b285dd102172c846d1c8de94a57456d1d12ce2899dd7bb3999b346543f127bc53c6feaabbf74a17e4f1cde2d8155c358861f4c7799dd661735471a5544636d56e2c5134159ef324b3e89f1b84e308660ba483565f27b8c2af3cd07534ea1f6338bada34ea383d5377a3a867280f2e15f1dff190ed501d9561689650f841d91b6969c158e9ae2193723fecf3a2b1e3435c297cf4633daed6aaec76bce29c269a9d67f57d78980d7ab08e48ca3645f9ba898ad5ff96d2ecde595c5989da568d79768ee42dce0e133e91fcb4289ebf6fa5c47c5ca56840919214991f4cf99490a9d3a587272ef0ce0cf81151d7753140f50ba8d83a721828fee5bd5aca88fe56955954e34626a4c788b00fa682b6bacdea479535fb55e8c10b101857b599282f2c652f494475c71534c9a716a0cafe1e43dc7cb92a27690c5e144ab08dcea5f530e19ba6f60d36afc087eff2cd038f1d153541b8ba3832b8651aa2f937da09ec510389fe42cdb9e7a5312a7c6b9f2c7aaa6a44df847d240b2bae855f3494a676552cb447033a0a585f6f23bf46bf0aee555f29e137984567b69124104b6c62b9071ffa094bb70519f965ed5fc7e48c1a385a5a7529b3c6b5b0150b160e49b5f0e5ec764989facd42141ab50b1d56f8856b8c8dfe606f682dafe0cabcbe09a9b0d1552857c14551745bda907295c7866f44e7d88b847141f7caf62240a4283ef5463cba8d1c5c6c706106691f31f41c4378e7959c6d634d6dfbe35938122072e0c695e6d18abe03326ef807c266ba7f2c34c47a6e1cc3036462c17d391716d407743cff9a435201b3c2892ca1805414b45f1c33a5d67ab1ea9577fc43a1cbd727bd12459be3912a07147ca954d6f8b1f2f7f74fdd8735e217ab1078b825586c8679eef71af324f6dd5e612ec065d54f2e0933121f0be5783f821480c76455ec05a28bed761cfd087269d8c82465576e21d7ebfebef5db8fd99a72c684fb303698ee48ee9aec5078ac5a74bcf9d9fe146d49c5763b8a214c79af25a4cc651e78bdb901a47d7a6bfd537d7868a179f23b2bce5ca50c4136eac8e20305db549e93f6e13b3852d9aa849513f7665bef0d1ebef70a8c14ab3c68f2bcb1e48fff44efc57018d94d97f1ab2e4d8a4e7d55b1f1b75bace6afb3504d7922251cb9ab19e5a16ddff13b274253a1be485770b49fe85ed10a5a901c4e596a80e85cbbebbb1ac9fa088ae118a64a45d800c4314f4a0c92ae4405d5a10e749f44df1eef1f33201e79006e33f84d40c1a916bec3941948e9d5a6a9f42279b984a8cf8f67a6a2e8ba0597a6fc4d9764916bd334665016f14a278d8011de30e9f1688764177e9fcff88542a45e58d6b56ab6f2f0d7b99b430b4f26a7a09991a181f0970a91a4b26af689551acb9e9ef59cc7be79823cc2ddc69b99d3b673e569eb80b99fbec86abc488cabebec054b7c8ab5b7d8db022290da0b6f91b2c0cee65684abbefb02093d525c5d7ab3cdedfd092a3a4dfa607b92d2eaf1000000000000000000000000000000000000000000000000050d11181d282d33", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 29, - "comment": "signature that takes 7 iteration(s)", - "msg": "1100000000000000000000000000000000000000000000000000000000000000", - "sig": "19ae6a59256e6fbd0771373e7a58708947ceb8122747527ac7fa697c0a11b4bd3b85d4601c4a755222e80c56809b2cfb3e07bea21ae7ab71f9a08808215ecee8f3e0385d6287ecd26430f2d314c16073fab6b609b9aa782c937425d85a5e8a40076a99c6943d9d763991189f2ecb5e6ebba238c4f33ed98655d99f837c5f380f998846c05866e8ea2d49ab8710ae4a00bead4e82dfdadd937f64f3eb68f73f30c7f9e0af1b2101c50e847413da48d3531bc27187a622a032b0c2cc004cf8964bdaa9236386976088d402f2c19a7694be2eb22eacc3c0878a9a6ac67ac105b0f18388c5629d6d2f15ab66818ec915e3cd21a0835b47d2d1c79d75e986bb6121f930c95e74b549e1dc1019a1eea99d73afca3677cb31a276907af768bfbe4f5bea7e5d7e2dd5f98b1d7f700e030c27cff0d65d224c2f5c84a593223bd090e9a87ebb35e5230292d2d83d40bedd8199c569a851eb0e7bfbd1ec41f5a82f5f46b4e8f939aeffaee84bc3b65bcbd1fc048e017be8e6a94ff2a17336636c5eec2fe30b1007e9801ae562f3220117d918d0000497ec00323c783f3eae8134e3cf29e5493eef07650306e6f6398e46b424d7c19ac3b39705ded999705d93f1effd324266c7229bfd11262ce1f40cdc07c56376189b775a3f53065e19fd34d2d8732d94813c62fdc646c854e15269fc0377351fbd3f4b0fc7de5058d0d2ee7e3057370017fef2c51494a1032dd72ee93aa3a4d3e6a96e37a2cd918d78ff499178e3aaad85dcb1505e1339f103df5da94cb78aa204f0a67af0cc81ad462c6818352b8bd1b8ee5b76db9cd1ae400c5c2b04caf353ca5382c72d872098209c36cefb171169f18b64bd3b91dc7c360f068b1295d84a259b638e526e02c6fce3b71fda3cd389105038dc3ef0220230c42f008bad41b42a66cfb80a394a697b474ccc03cb6becb27d34cc5248f3a97c58b0b74bdc8f29acca5761020b4d802a2f89232411615b616d9921fefcc64f0d0fbf37d74390d1a4c477e930c9a4260096dcb831f524736c401a0d86c7189ab169fd82cfafd0fe809ad8eb68a6ca7a2296a1cc5d1d950add54577374cd790ec0213aa6f5c0c54ba53e22deb34ca320c3634edbbae2663d7c7099f8af277aa444e19a55fb3a6d343416a39e5f292af1ac3e61b3f8ed66bb99c51c20b7a70753b3f676b6f05c9671bb5eb49bc531d60efdc7266c1aaa8cdd26f1a12fab3a732a8d8bfa96251e2eb8737041079b5cf5ae46a22ad070b8ade304a3c10a8eb17fa20b5c37b1ebd69a105277ff7aa2fff53fc895f01a4c16ac4bc043731445d4f397a8af51545f2a6b7dd07432a9e7da5e250fd55336060ee91aef91ae64de1e7265bda62faa6d7d66af6a30b9e280b82dd54fd6b4025eb87e191c33b3c59cb8545cd91b2c7216c95398c56e430d80c30a5786bd3ea5b9cd560e8f4f1fde51160b308fa09f06631b563407abd72a5aa0e9433dc14b028337e4589da5082ff309a4f54f28897ea83dce9a7f00c11b460afc6b7f468c093057a91cad7debbaf4034d22d1033d64a6a53afa0950355b1fe75ea7e76359bdc9715618c637a795fbc5624b7ccef1bf2c456fdc59bebf529a46dddcbe05f94fe474fbe2f67a37d21e1bb3bf0ae5b1529b1474ff1c30effbde1829ce4c70f12e9ed8f6cba5e313f57689e249786573ae3fccfe836c99154074a3e25d84cc3472468efffe1bd19f27c2be739d9fac4f3b0eca9e0dc422164fa1de778c3e2e963af800feeeaa5777300905ee6b944f0738bd3ac70b07f07fd44d1237d20938be34053f2c0a6df8b8a30393fb6c8ce5fc9bb0f16183bd3b8cc2ac8f131901d7d6c5f977f9e00d2680cbddf58f53e69eefd7aff151c07059114eb1023aa7ddc8fc499d828e492407e3ada888dff688e9059cdc14f2c24682a8c08993015818a468c232294d60a635f39e1038ff589c3d5dca5f4e88517c81411d958c1ac41f32e20712335dfdc535eca3878b241a0cae45911d9795fe4129d73605831ea06b2a660e0bb8db8507db90724b8d43444ca9be1a09dc5850bf6245bf3d67494fc522f5b02a3b605f7f57ae30dd3553de395804138df9d4e618f5415941452a01e40c09cdf84d7f843767ecdee863b4bf5c60292dce9b017c3b1a9f30f5c3143fa78bd17038af67cb2ff1c98aa55c8b9cbc1901d27be5df4e926433fc0e01afd4b823541bffd88feaf94a028c7772355d0a64aa18e0f1d1b239a84244a3f5238774a7a259c4ecd2794615e54adf59cd38d2cb315262a22b85008093419dd22efbf27f06e14e1d50661dc05dd9c5074c71187094f2374d0140ea4623580f1c3c2f8677cedf77bae1c5a5b7cb1d2b23db343311cae4fd50f2424d298e0c236023f0b53b8709622a7f0305197fff2caab0dda080f392603c8ace6e46f7d1cd3ee7ef7f74372fc2028d3e550afdd2085078dd373f3a27fc2975917921f1d7ab796e8c77f703b1e7201a48ef5fddd465fe3ccd2465ede8049d54cc60d06fee0e5bbc2912a2d44e250e0819748c797a2a44b395d86fbc48979d6ac808b2791bc3b11312d4d312a46d835e5233fc471bd7b7a802713d2d1be5eb7ca8378b5c2c259f91721f6ab3e1a5828e7804f9742adc1b3dbf5a5367325960087e3976db60521ab0bf559aa43e5cfe6f354cde0020ce894acf4ec56db0bc8cf49f17fe0b5e00e147ad50736360ad39bf5c561a8570c5472da1384ecd3c698a9f4988986e68cf311150ba5926e56c0b133d25d58d6d741f7a764a453f370161bd258dd027eb9cd8f3a1aadfabaebdcf7776a85bd3ecf852eb6fd38fae45e9378637b6d61732a7b39619c2c5eb376387da563874cb172235c814593828b2f3ae8f1dbd51d27b73246acd8997827c9bc6a44364a3513a9e890fa0eddaaa2c69ae98934ced34d97866089f4481f02bb53009a3140fd3d3fff07dcc0907202c7b8c2491b046427e2278cb07cc61c50fcabbe3f34dbcd2ecc5ddc5139a1f99f077c04bfce74f1e25a28eebb1e1e4210c3bdf749387d02f1ea9781b71d2ab447c2c9eda39cf0c95b587d2083a683979106f6cb8dc9667c12078aafb97d65a349e9b4b8db4ccb291ce8de306b53d88a8919bbbbc2f245d03221b3f7791ce7e86997a90434b588d08b547bc30072e962dfb5458d2e47eeeb2c08f92fb3af636bd30dbbcd0133c7dc5a0ea56f1ff4566442ed974addc5b46e79b7801bafe7b70bb216ee5e85a8ff6cb4c96db1dde6f275a9273ac670fbd976530e0d4c760c4857f26998a4e2432d0f2fc419213bb0fd6ebc2c600dd027d7d0880aec2cb12516c53d3a322e353d683a0d0a95bf42820ccc4e2dfabb329ff7fa1da8493eba4e0e0f117a1c1e5b1000b63368edd6744bb352dadda8b79986c47641d500c826b5d9de721d7589b652bf4e085b977ff1494e1e3ee0c730c7fc2b9d9a3a290b63ceefc5bfbe47ddb9abd422da0b347e56be4f4385480955b292e272665b8e59bb697a30c5dbe7972e28088da493c81ecec7af931c72eeefa2d97f6f0a38ef4c2253b2a45971bcda5d2495d1194f3a44f7dba53bb93684ef7fcc47e11af588aeb7e8196dcd19cede976a4a69345c953eb2d349b2114582bf992cc275c764293082cd02554d82150a4aab3561d838f2e4185aa0541d6eeea34c690390e2995969ce77c4e3df335d349efc0744fc2f00188b26eb5374f40912c8abca7af30403795b04ecbba77865768f8bc74e3da3133b539c813b7de96b422acae5022944722f055d13416566e8bb6ae3e87306a4fd94179beb0796874f38c6f70f70cdf829e655f23f0783b37d4043551f5f2b7640d621c7e823a2f2752323065df7fd85f10693d0355ddaaacd21c147005f6152d553115f69f4e363cb1a918f25d097a8fa20b52bf73fe76bcdb0b8d47a4e90d3bc6c49aea17e86b3ed46fac9f3f010132c13355300fba6af903cd10bf6421001c285121a09e024c0b22f303570e64d9ee82eebd2256532ab1bbb97771d0e7b48362625179a1e76e8e32f02be52a99b1af215cab44d1c4c938d589f15c86a962f1b6c9ce63d6969b42b79c450f684c4e613101e6decaf43353aba3c3d06f14e20931a227bf4c329715274dc92fcb3a63a469556b632821ce0a56848235e727699baa4d34741c799355b8dd4b5d6b3b9bcb9e7f568f67964a582a3094d512228781c322fe58c55342c2838e4b99a067a60a0fe0e58f39935dafa0f3943f05439e0e9f5705c23385faf3a4a132602302ac3eb68473666fa16bba0219f56af2c02c1b634e6ff07c7d29fe1aabcd031592a39d64c579492d1fbaa18834024ef4b3d3bbf94bb51f4ff360d96f2477ef2f09577c1ffa466c79657cca2638fa627fa478595d52dcfec7e535aa9073530527b6041e4718275c4ac4653520ec18b9e726492db278a8460bb6cb3b5d1942b39da670f48829710c2fa5c6ce2d6c22be7ef3a92467ba228c9b1b4390603a640269287b583de09b68e5c4ccde813450755e332fc242ad428a1fa977011beda483c88d14acee94957c5102d8451dd4f488231b1653c79e6a0037fb931b1759824c1036b9a62fb69d65363e8070435f7b473bd75742138f771af622ec5604541f78a58fafc526d74debcf10843af616c188dcd1741ad33fc8af61b5ee5df15bd5596e5504e437fa57658610d6258e9d7bbb7b68bfb01965f52045a9823ee8c7c5207c6caccee4cf5b8a664b6bc80a4d9a31024472087960a8f7a17609eacef0ed404ed42f5f2ca0248155efaa8d92a8d3881fd7037ac9c7050beab52ce3ac04d84820c2d40ac1a4fcc0c2e53adf3b45ce5fcb0543a4ec14ade338cd410b08e873dd6c69a445229220690dc3ee6aa1008a42e95b5b04806cc149dae474059c14a4e4ee70fafac7e0f9e6a46eeb2406dc2db6804d473753465d92b5a512327a5390f6e9b6b9dc1cc7d26c2d874f6dd408f200b75d369b141869179286ff869ebbd6f0aeb4731f6f0fce75f3073a56eb2da03e5aa4e7919bf8a8e95aa0e739d4625b22017d0a959164d3c850ddc3747a87c1fba157147bb389f139576268ee66c3a68a37e44a3efa024e75601c9612c25292393c19eeb7117e992ebfffeb2d954e169ef13c793d4a1732b1c6c514203439f9e357608c9582a345a1ac7160e531906c932584603ae033ed762902e629985269170da62c4a0dcb942475e84f4795a4fe14eaebe6d81c8449b7be833538c2c48ba00121ff71baa112784775da3a97952204e7c36667b032d0653c7a1fe6c049c55f06ef6e7fb2d082245caafece7594640ccea08c41a3c8e0bcf6e9de3c9aee6783d5ed106c106fcfa661e908a6660c1703650eb3b0214ce947f1c3bb17c8b9156c1c40e192febd822a9ab1293426fc80ec117b1f8fde63ee0c22b743b4b4f334df749933ff182186bdaaa3274c0a20ee495d195a59c9bc437539d46aff19d5696e199e9128239e23a94715a4d9cbae6fcb8ddc7cd299b47b9b3861b1bacf703ff4a365548c9f32f5ba8c9e963ddc29415aa8c46b602436d35ea864ed77b5faccf0ce4c4ecf2b9b076a10b25bb9a6bf75eea8b5b38f6ed9ada84baf2267a5068964802c878270f7c1e306d01b9661889144fe799a49f17c857eb03487a4a26ff7bfa247dab3384fd78f3c6ef2c3b392e1dd950c332ac038b03b72da8df56e1676ade60cc9e188303a92e3eca0f4c4fd0f186b30504fe107cd80ada4aa3e3de3145e445e267412e9b5392a457d33f80f010f19f5dda7f3f454eb0e26d24d426a146259606b42fd9e2ebeef0dd8ed74692259ef869c72d9bcbca0ad16051083c0e7ea52a44e6746a278ff04e90f588fba34e812e7e7ef92e3561eda68835bd2c32c5171020f6f9aaa95cf5c94367ae5907e21a04079d637caa997145fc20a847bf36288b42af90817074111cc12084bbcb6abc3911b71ea5a6a2b7b3586ad0ab4eb5df7219ccd110363352cca2478cab48259693c5ccf3d8b5013eca415762984ffe1868817143dba4549f20abbda0a535e7924ff5538614b924bbbfdeb2e582d5fb99cc9bfcf8bd5cb5b9edd7b509370751c9528ae35152906c6003e136484ea1228c7bec816392c42137075d07ff34b7a01660aec8f1fbf2c4983636403161593999099952a214e5b48a5fce0572653e0ebc4b3c610bcecaa3b1247bb3dd079a4decfeffb28ff53049878fcca1071cdae4bb1aa43689a408072bb710e7a7caecae50d64341921d502aad2a8d44b8cdb9fa8d7d3d19196665493bb4e863b3d465a5e5028acde200750ec9e70cf8cd64c7904a75795ab0bfc609277e498ad9910843ee896b08772414da82bb92641a5f366c3fce337681660af8aacf531be95cdd007ac254fd4dd17cf97890c986afeb1574e2b7954796bb6a089b72aefd8678bbffa5413c7530c2ec532b197d9298a13365e3c5b86bbcbfb6266728190c2dddfeafb080e6a75add7e67f89f40b1e737ea4aecde0ee2029a119435a9094a4000000000000000000000000000000000000000000000000000000000000000610171a1c23262c", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 30, - "comment": "signature that takes 8 iteration(s)", - "msg": "0200000000000000000000000000000000000000000000000000000000000000", - "sig": "add2b5be4a714a4161a6c375c75040b0d8f18362558186b02d0e7ddbee94609b75852b9b8fb97d46f97a1a49b40aeb7df51a142773383f51a0f427a39eb5f25e5a2454d0351fce1cc35fbaff865a3251509a0d8aa4ebac94c12e5c11111de62b146996eadd88df752577045ee2edbc9c0a81f0b0eaf40e009b0562ea5c0af73ae2b5cfdcae1630b3ef0cf9e206f8a6a3698dd130b64ef2701da341fcb62de3916512756deeb90e3c6d67008acf3b7e5198fec166422ba555dd344031d4a1ec0901bcdd613421f036f7357cd847d9474eacc68e8a9d381ecad6ad57f07fb6747a9e47c1c30a019eedfc645adfeb20636661f0924ba943f34b6e635d9605c07d34ac17f70aa6c6511c74f27bc10dfac35c48e2a1098f34235069b6c12408e1dd7a0a9f2d86a561118f53ab6bf9d6f77d0b55f4ddd45432262c46d9872bab7835ddd4ee32adfeb25cafb17c36cbc725b697fa37f691f6cea3f8bf4fdb8d5378029cb6911709c6df304abb944e99dda32613aea539f249ecf16b38e7930dd80999592b1c4a6d63d29097bf9dbbe1188f33a7932f920297abb436f717ccd786e5c1d592483e524a9d91da855eed49c091fb03b3090dd6496ea100dbd513cd9afc200db4d8c0d887271b6a63cf8431c73249fc6a359a5b829d0645910a8d07d36e06cddbf6c4f6dca7f6eea50dcbcc23854cf03f773d18974c9b8bbb83247363614ca147ac009a41c9a57aade43808cee97cbac2b235ccb2bf3db366a06658683d16a73485ecb5d31a268f9721b15ef790187525d52f6ee7b3678a5b682e04f0626558248d5d1274ac7c90b777a8ab75197e92d766a42e2df4df7c09d24fbb4344c29bcb179c684beba97ab512285744298b7cf66d33e2e382a161c49f11cdaec4820236a8af2cc5aa551338cbdd814028d44dc4376a7e4db40e77a034eccf07b59eb0808afa5e319abf72aa11cab07c267304b2352112d42a0a276bf7b9fefba2f08ffaca25eb67ca180d7c4b581d4da047e6f50f64b450383fe2ea1abe0d575860e9cb91772619d5f583886ad2ee395245e3139ee877ac9ddd66aa61cd9c0a36282e9370c5760e441e18706f3dcdca3e9977043078d50f69b944f0d405b07354f42cdebedf22133076a591c964b7b31ed9df3a1c26509e30a90e04ed45dd1908e7df5bf882c64ffb93e0b00ee20406050d1be2a20ae85ba3715917a36547e39c7ebb314d5ebd3946635db38bc7a467c462487149034d264edbc90ac6b591e088476c458638299c268f2efa7360b71224f4acc8e93b0d0eb314a143bbab70667f5b0bb199702c31c50521ca7d8fb883a78a12aa081dcbbf0f9c3ae18cea1d98d06c95387d994e7ea1d1bb5a60c89579cde48e7c3e103ddb3d889c86c879f116b1f7cda05639221ef2f9b4245af759780c1a3d9ed65cc2a763189146388af57874301ef63c546d04f9af09a8ff14697ce43eff672946c3e94153198cd6b1036d2819f6c01d1746fa66d457073d563ae81aaf2a9634714fb52f6ae182fc2990af8ad5838a88264c3042cc09af7914952f2aeeb3c9e452aab0951d53d00ff38f73881d665ff3ae7f8aba1b325430b75cbe119ceb9b4489f7bcf884e48e0b8eed24371b82663d53e96568dded90dc8108c6bb204b5b2c2bdc3abf1d934ece6a74749fce8e031dc4edf8562432ac1241e3d17b5b7a4cbfbc0e80d08cc7b4ea0592b4b5f806a58162635b30c194a6e8cb749cf61ba5202de59b4d8c90d328978d6ef041d0f787cf2073f85603a61051b537bcbbba06089ed0cde7f944d3ce905c13e7dd003a0c3ccb6ee9789a4edee386a8f6c0d4e2c56fa2509025605e106280e7367f0789be4d221d6788e38d0623ca58315df7eed08890e4cd631a019af4e8aa13ac8d897507a8b2eab8ffb7dd0f0844edc9ca448799fb0ebf11974c4aa9fdfc4fd2946cf74db9ab3d37d48afdc522427d71e6ca5702db7f78f535a5cf1a85dea6bc210b0a8e79a718e0245019ab10bf5ab9908187e35877d00c8daf811a8eb2c087d266bf987e54e4f9bcff4f6eb79c01ebe28fef01ae2cf863774b405a8e7ff6f8c0966171d95b7abe0bf0218b7df49f8387e63532e3cb0370c15e73e3d0aa63b05b7be8c06bb9843b0bb358c5215eed6d34871b56cd10c081d54bbe3a8ab05d807a90e37d4eb3d88f2691d2e7880d6d37899112064b693f4aecbd834633ab97b74acaf777579c2ab8b5d6fe618d415a937bfd09a5b3fc73b242f5bde8fe0d3f2b4336874c49e00c8426443811df2b1f296f3f1618ccf2372246b17f38565dba0dd3cd4ed2b83650e5ca9cb948a49ed42537104d3b488e06c1f05c3eac44c3dc0f4d1e6de7ffa8995f670471d2a4824f8fc66a6d42dd3e848d7fbee1defd9cae3d1e70adfe607edb58e0aefee5668e8b03cfe3ba3a881b2473fada1052929547be1129c825dbb0ce14e9d87cbd16936f8ee6b6e39034a2138100f8503623be68a0162969055aebd89434443c966e7064bfc6e7c3cc99d63babca4defb545f69432f593e718e1f922f1e009cfae0edcc3dc1b9321fa050db81eb8fcced9998e956289b601b4e972f25d8ed75726d1427228bd0c0e7d9e13796bcc2270d40532771d3237486b62df1cee59b4f70d5487ecafa655cc70c6bff966621476d3c7cb2fd5dafbec821e51d9e6fdf46ca85e0e71c68f5619c925c409ce0bb46e8bf8af977abd4463ccd5f6a87a83068a8f35793bd5c369ecc458874b3f03886d0a52917d358d4488658b2932861394c866408dcf896f83d70cc0d99062a82e40e5563a9c16204537ee305b67e4fb2d1b5b3d2fff82a97cb56e4622ee9f1e7a6b11a4e77180bd5ddcf197113ab4058528124a3a01249750e1136614147eacec91b271dc23a2f03be0937ba73d18d912f2e546ed54ec6c11c9a7d1c03033969aa79d34eb332ece85d5956a42f0ef1f156fe4ac80b71a0c05f2a3f3c2e302fa600023b89d51b5ec660a9b936209b4c0d64f82b197119581cf0a54888fe62039eafb7e943d9d554dbce1b3b0ec2e7d3d713d9ab8aceb61b941b47bf9745c6f6620b8e6ef1e072e72ce68838be7e15b746de6311844596fe9a0e1b60f52632ed756a358c810f26a79c38f6f0d0a4cac9f9f8b5a2232147ac457d6693d4725c6651ff0f5529d6c0ddc2f1e1c90caec33618a674e729e40fb8e20ee4468569c1961f1d123d6d5458ee1d3b3b0f887df8b4ea5c0c7b71ab4da51c254116808567db12b636beb68d2685aa1e6b8b61f9eb3175ad772b46d3a6ba4f1824caf93bcd1f6cce75975ed6cf466b7bf7f319d58a75dc311defa64e6c9fa4a376fd3012e39ad9bac291b93a9df688309ceb7fa7592233350e049e97f505dea1480a8220a5a80dd3a7d05980936239d5b0f9904849e3744969a5fd76f953c5a1722eaac6461c8a0001bce55c13ae7c9d7359fcb3b27bb22bc7251102bce42852ea71cc398e7a592503096da0a8e284421b73f07d893e711bca3cde2ae7062f5800fd32a57bdf37acf8d0d67533b767735440d559cee3acddaa03eab2620df9bdd069c57c4da27fc4b5ee3e1d681d42a312f0ff0e1d5cf93a03d2517cef4ba96bc3688feae93dd6696cb00b216d662ddbdbe99c58bdc2155f9591ffcf9dfa66fad007a573c7f1c61ec88d9bd88f458c6946259e2ddb28997b9238ce63c6a065e16742dd538b4feb4b37ce8519c19c8c00e255c409e236d856afa1d70c5f7933b492a086fd00fb321eb8f5dd1dd45cf31e8ad367d5fde9684f7c0e20580f832f0ef0d5e0f3e617ba6cd1a8ff881a695894e33fa669c418f423d1e6c0d650bc48fedf9a962958e0a873e408ef7a0787fa754198ac10ded45db172fd1dfe1d9eacb88961afd3f45d186912d35892176fd400f4449c4319e6a84ce317b58a290e6d56e89e5c3d3337c0b787c9791a586270655310983c80191d0f7a44c79512bd6064c542a8b30c3773b8f88d7b24fab9e8da9c2b35581bdaddd272ab544b294fb2eea5ec38b7ca953a6e15ae22fe4cb9e61c6b7d93f361de94cbf370ebb4b80993a30a03480ff9a9c21f689e04d8b387dbcbf28fbc43cac606f0ef73db86675c40a0304297c0bedc2e99043096f4d4324e7580eb4f166ef161723e76eca3f3ceb45ae34aca1d9b53d944c1a4bba787762737c4eaa6c0014643a9abea775b613f503ea3f282836b6416886732643dfdd4a3df4a954e1df9befcb13d7e3757bca76f2b6204e6628758a904a44be528b06dbe4e08f3fcdc949737016b1793ffebfa2f1547c4c3cf7d083a211fb21b138dd5d991307b21d25b51f68ebcaa7a6e8e4c18d3e8daf24e76c767acfc2e1ccd8144bea8f1df8fc874634d56859d171c8a29ac1441ba1ab91ae66f830d8272bd878eb1c113606062f5b74993b600d1a8a90673f8a9e26a14b534e248e130787bf93a34b4a88bdf27dd9261cea964d2dbed15a202a303d07f8b16cc9ad4406655b3bcfade2554b54bd3218ee4f4195e217d3bed4b47d05679fef824f851dd7b132048470a31a54b3283e5e1fbb0a9d07758294bdbad06c3079ce69ce80dc426b6974f9d157dab0c5ff4b696f9014053325a3c97776eee69c92dca37e7ea97deb9d39c8dafa7c054bd9dd85329761935816688852abb16a4cddfdfa62e810c05602957eaa76c9234130b4997a16cd0611175603669538ab43ff75b83961817c3e7579c7130d316013a3b7415c335ef922440362bf9209af1358e8fb4379d8b0ada9c19f34ee5246da271b5f4cedaaee27587805db201c9ebeb70ea19fafeb0b20372cfade0ff2a2e9c3158a74bd5c7f5cf1402f796535b49fb2a8c53a53a29a9e47acd75f5decc4f4accab88c487507ce68854f28953c90ffb3fcda12c0258749088840182699a98106cba81e058cbef2f0873e5235328d4312e939bf657803217121d0d4ba74bab63d8f30e5633167fd72655e8aa7e095063fb382d75ee301855bac604b26cf6f810e781c931f152688416f94f24a9084f430e48df6a9f71713a03eb8c7bb15f799afde02c60a9c9e5f4038c03faaf6f7583cbbea814050d112fec0c82428145616879d8c36f86583be2408787d39bda88239fdfaf7e260e3aac07e61972e43a3bb5d180e75723889cc0adc482cd7ffac3ade30ae156f5a34940ce78f154e0693c664d03db2ff47c22dd5eba693e51bc799cceccd8274c4d47ab5419a33e42336e4699bda04d7402f9e761de4a268a99d4012627944ec15afdf4abb4ed0f87a03c5928ee268164ccbef16eca7e25cc63a268e0989495d47a1a2be86bf30b0953d87e0f028e17b9d4744fbf852d440cdc2aa8933f70f5eb9f1ff77fb1664e318a9c5ad7f8c99e9435c47dcb796392f9800e01fdd59affc603823d5646eb22b4af31982c233f5cb814d8ea069f454ddb0912d7429993015dcb5f224d2043b86c26652235ff9afb60c0c7c01e28c5c4f03482b688feb53dba8771ccf277eada93941677b8dc8372dc04e14fa574360d6d8f1756706db59948a5d947598aa43ead8c1b5e33889453bd24bd2ff248ebfe065073181095fa9f5a1c0a7496d0b92cba2490da100dd845ae5bdf4daae19255787262620bb95697fcc2227778854c4a64b2e9ad2092f5c9e405a3f78c82c4da3783092d0dc8c23b4b6384c35c804049a27f1fcb4cba07d13218e77b07553f29bdf57f3839dc8d7ff679c8e29dbaa22ef16340408a84682e709667ee8914c8afcc760e43089b006b6501925ace2298963bd9b4137e30a37fb98223c460ae046d98f3778c1a131097884d7fe80790039b0f521257209422ab513a2bc07003dd286e22d7cc92865c2ecb86eb5d894fbeb91857ffd4387641ac6765d967efda7c33abd1fe96a7b28531c80f364cff5db3371432e3459f8faf0a68da6052cf6f0ccebb5334f5a917cd8fad1c2927f0d8b4905e73b08e26a88c8c3b8ce14de97f3cb97d1bbf064bf2e066754dfb7c1c3508bfae9778e2d20405c4c82c722b6f5ead56fb0834a47c35f48a732b8c19d88bff75ae488a52ac25b4b9038986d453ebbcae6a1bd8ee6b817d2193cd51adbd4b4f37c0106dda8d96e4e46d6b74152aae7706714ac6f91880d0de53d096712a1fb04e85d59fe64a2d5acca31d1cd08fc8891b094467d0d26b8aaa637ff6033eb9859795b1f8848d0877b8f581780dbfe9d3c966ba3c55270a325d1cf4c75f2eb84bcde48802c4f0430642400f6c0ca126bd0523417933d51e8a99e8c87064d1e96713e9aa7c7df5956b1a38465cc6c0581d4d885a2df6b0626fa96dd4b20f964fb26273d48419170b2ac9156cbf61176e872471824ffd74bc8278d657d49b5c44d1e503bd66736093f654d2ed0b16db276cd639abe334079bce91d82ad49333884d16b47dde5f60e0d0e4fde7ddd5bce3586fe74e83b0851845551bd27f5e5ab65422c3a9da9d300101a213faaf7315c778996c9000562d3fc3ede0f36545dd1f6010e63779f282b6c7d95a1afcff3000000000000000000000000000000000000000000000000000000000000050c1217191f242d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 31, - "comment": "signature that takes 9 iteration(s)", - "msg": "1d00000000000000000000000000000000000000000000000000000000000000", - "sig": "81208badc206934e29b2c650302144a9f0fb2517ee9bc79c9c40d698141187805ee71cae1d23ffb1f6ba8cd0f5679dcb197780cc6261ee405a103c5d262399b3e03027ef2cd9004c57080d56ed07b08f412fc9a1deb9182c97ec02070978d416404b23a45bb005cc82e6eddbc2aeb0b9b984a0110561a49f4ca6d13163d6d943297a5ccd64439e254150c2dffdb119947a594923e10fa97718627355b64aeec1448d96b5b76160ff46688cb79cb3a8f67393019226329613458fdd6fad3b111ee576f544a489495385c6ec1d1f83cdd9b4dd62152e81bbace1ab62cc81ae47625cbf1bd21c769d3f4b8f350df8c3a37cad42d92c80c3f5e254fdaaa10c1a42bc6284a13dd7d5505f77b3afbc0bddf4e9f434448cdbd9860bec44012425baa77e33fd1000a4ff37ad79a726704475949447e27e355abda42901cefdb00824dbc4ddd3e64c68bee668840fb4a7642dc6c1b9cdc31bea1a3f13fb8b86f677e2804b29c5c6ce393c9806b3623c47330ff1810d026a2051636d26cafb5f4087ba4233747ebb84697c90e955543cddf792cf4966604190f7c432bde90e767192b3926372603acb947df8d083d6cc3863f59225d30e526a200557cf5b49a35b98864f13eb9981f9edaff3d9592188e0f921d5091cf4d070d47d60c17c4199d10b8c1bfcd3b207c6663240c9fb5fc5de60216967987dfa529af0481e030e831be2b7c6dba79c7da8cec2dcb5e7498df1a69acc1c5c04f04a21b8709b224198fc4845d0ce7daaa179ca5e26e75f8362369561bd57ec9056bfac6999046e8916d0af456dc87f0260f2bd1e4cad328be0af475a169041e3ec9ee1f38102c38b07456daad7a380a8c5838e425c96bd370e49f8fdea521f06e2410f04d6fc655dec1d8b4573a31c8889fef8f57c732734b34500ecf8d7d70b71ac0f6d73b74c0d46dd3bb316ce3eb13e757a34d9ebeb1765d54ef0f3d3f14dafe6f8d395d7ef6f9a7c31cd8ffc190c16075bab80f1816b9628ec1ecc057d4cc8d41a541cbb75352610ae739c447828fd107924aaf4d71f0518650567b08b7437e08ff2de32eab8632b089d2698b03dd776d7ded0f69f6e973fcf50d86e8df073bd33b9b6e76591b9e4951688c8b7cea61974e9b965344edfd20854bcd9ee6be8ff323d7aaa1f3a9810dd4a7360214e89ad370bfc22789a5d2dae4429d958dcbcac7e695eba18ee83a6fb93aeddd28c144d574134831020808728f02df257c90441aff43163fd53f207dedfb7aead97a80c9b8439b6ae5a623af9f8ff29f2a475d1b8e3c705c073e4149cb3ebe73058df1a6461423d9a99264949342e3a43ba74a00b22c1e111c44472f2f884951e1e80d90a4fd22d44432ec9520cec90ba51c82ac2dc864ad22166edbdd4d622be4ef75b67ea0e35bc78e01603d286c0e1132a355c85a21e0bc79bac954b762ad7872a6b2220dae055e8ca6dfc88bdf6d4a4098d5e4f1586b9126f8c75c2322ba3f4a51e8820e0a45bd2c603347386035a9ba754cd464f909bab4493363e306e90a73ffda3a21b2985355f1fa87c3e447bafaaf7ed3891c6c475276f7136c563e3500973e45f319df6f2b8f1909e35faba0772629da3527db4c9b745ae9ec8514e3c0138a2f0abae5128554ffc6bc45c454756c06040c319535574722e0bdf612340adde7c2164578980081d682548c649bd482fdef2b7d8f4fdac980cfd5c1c26b5f50df7dc4124eda69498009723734a868f01b10b5ea004908a6ca838c08edb393cc1dbe540e375afa2161ec61e6c1e2822aceb9c0c1fdaee27d2bb020e7d39cfc9486afc3810d120a807606377890f2309675398f55aba36151b505c737115a27a020ef85184bbd531afe152f88a56c4c3a914f40a30f1a287a7412567484b6bc033621d70b26bdcd5f9aeb2a63f96846ac6ca8bad6237f19b8c9f96ce65325b2b4f46977f8418aefaabea1f27288fe72211827a2ab10d3e4f00300692ccfa3eb7402747908e2392a222362151a89e35282b14a3b036ee2b207494cd7cc347a35b62d48afd5abebf305a23170d77ab8e11ff575046a69c0b5ee26e97b89ab3d7875f26db4aca5107b5d59ba3027655c51ed2c886efe750231cb2f9b80d83c893a0ea0bf9777d0b5b6d9c08344b94c45798bea89ab6da065de190aa2c555866d584cede23a21041a4336cd6cd0aa680b5baecf256b3f8edf12322d5206b1521226ff277b584d166308d2c94d4eab40d2c39fee928c98a1a6832e634fd6ef7ab3464def3f711a8e2228b489786a543865cd2cf94183a56c0a3f3cf2bed33f375556e7b8b9c51076c0c5f424f6171cca215c4f4179b9325b1a00269413834d39b8e2982a78b58a9ba0572c32835c6d6cd76bbc568b78d0150e7b453a261813a4d973f86111c35308e58edc311249cd6bad236d608216aea7e3bd6dfb76688ad4923a17520a622ddeecf79420571d75bdbab97f8e6f28e093a12bd7201499590a9633fdb8d572642403f4240a445ac8873f27a109da48e24a2fac877feb1f60f4561fd0c81e922afb1a21acfae18285f3b83f47c07ef314a85a469996bea7daf52a19e8bf54ac5e9ceb9a27340ca9234a06b55c3da121ef069d440705e52afe75a7721f0b069a6e15660d5962097293a8e184ba11937a39471a468ca1b390eb993b4abc22093020aa2323982a5f158ce35eab0131dc0818def4b8e8dd1ee04d8f6336db293a8ac756307c6fe35ddb23b870adb7a7c873ae86cff219590247bbd1cea96346032baf29a208a45b1fb943339fa546c74f95e713cb989751ffd2ec70e2075779d2d514738b5f224a432f6533e7ed532bfc6d666f50b1e4ead9bdbd7239e4a961b71fb58e5010695c5776d225b480e7e15642d29e2fd6baca44ce88672270665712834cfbdae6d50d6219493f9ee99e4c6c2b7a2e2c961ccb571578f7dbedcc28f31b0d7a1f52b49115f181610d59289aa26941de37943f886aa651f90a3504cbd08e8876f3f78df2cb13b2b7bcdf81eb846f5e8322add89d0e24a4433afcc29296a2274b7f90db463712a47c384c35adae432d21f4a6d57127a6695e5ae01e934627382126db7fbfda6f274f370f8b43711b817efc58e877a0f91b57a080099bd2578ee9e2b7eca74be8bcbd3d17589c373981e41d24c256c90b8df08931f8dda856e1adc570f73bc4322b72f4581bdda7c04d7454bdd8c713840396fbb100f9c8c3259c136ca093c71b68daf52867fd636d7e42100f5994ec9c054466ccb6b1b3fd752050f2723c1094fb980610cb0d3f4b3dc7494b1585e438f5ba9cbc1bb0d699db55af160b51d4ce8aeec1cedf179865f5db751268af64cdfdb0426db8675583b08f12d623be782d56bf2e3bade34e7c0da9ce26998f0fba11f7d875497d95bc7849e94d4d068a066ed949bca4bc660c6aff94d7765b4b131ea6020acf8459e2caf4f95fadc7bc799252cba9faa8ca8bdaf773cd89e6030194ea023ec465e4ff3abf9a147fc68006f37c8af325ba6975a23343f56252e76138ecfe40083d6baae2e6689972224fc11131231ca02c8ee542ef3998c4a1c3a934a25a2db2b5dd191d62e2c3aa651b453d16ab188f0000e6d7a55eddafd037c4ea9c2dc67831a7b6cfb39aa0cb28190bdc4569bec63e5dd637b8e554fa47a5cdac33ad058eca681dcb029d843c722e56157104e53402b15a77ecc1a910eed6108c013e683f9c3d1362cd04954f5c2b0a5952d144e0e214633761aa6122f9d336e6db9c440424d149051d93697c5908ab58f7e73beba03d3e5884fc37c392adea81e971c1d4e6066f6ff976d8986492a1eb7622545e6408bc7ec6bc32de635095ee15e31e6091c671f8d9e18147e456533272f100265d621e59a450f26a4f54af71ae6400af8266cfda533cb1f23b623d88c7df4fb9267c0a372fb56b780826bf2ebdc8ca83635d9af5af3ab625059f5b72a9d417a9adaa5323977ef5ad4df165b6790c2f15c09a7dfed04c501db0091be91a89c0d73d541c4338638478e27e4a8df07d150db1a1ecdc65c6160da0b60b6839c2b27575bc9318bfdc91110a9d476cdf1e8441c83e749bc6e6147a4aac60d366e622002fb91c71c287242c0b30dd02629b515614bb16997024ff234a8c01b72728bfeb2baf937685246f73bf4472ccb1456d946001db783221f03e1033768b91bd880e6771e00ab00cc73b20ba7516ffa463bf141e5e033ce9e471779f68ed46306ae59bb39cfae44ef7484af48e052bef5ffb09ba17f7659ad9e64cd8ea529849dba63f08acd1121eefbfa513b34665c0287325afd11d85e196c2bee3c58cbe18d627e7cf055f7e91d3836c3f020f9476d34eec9231f03a8c2a33633698968aae9b9132420ea0468e65b296d3ecc5193e2bc6e0c0835bfc5ba56c175215e18a92b6bea9d5a2ef9e0e5de0ca1e297515864070fcc43c8f4b3abf89a7ce3e5177e91bcc764daaaa63ca412cb51b0153498c657a5ce15691f047874c9a8990b1e8f20ea408a354f3c507117c7e7a7011c030d137726e23f8d394c1e3dc3bfb9dbdf176ce1912f11b4343f0a5ed18c91cca4b04480ab09514a50bbe7732b81b10f19b521750cb1b165f59285e827f63d6383e7c5fc0bdff86d2291e001f81b0a55080f2a5355d8a8e2f96bec82691be0da2b2d3d53f1293fbcea91c5f6764a67f9b6f0f597c01122f3e73ae53dc5eb532d7de81eb8fac85746c8c9cee4c19deb53eef77a40eebe5dfed8f8a89851d92b493168032a4e1ec3342451aba0318248a41790ee2046cdc60238169ce4e700d101160f1eb1143f383a79549bc0aa7d7595f15d0a30ea23f451faed9ed18b1447e9de2c79cabe33f3131c86d1353d48432b7091bb4d1da81aab8102790425da4a836254498f34ff0e24c75912ab36473fa41576a4e08c4fee36a15cf81420667022cdf0000ea67d4fcc2258c63bca3500080df4a8de6c9efe5a6e0e48427fbbc848a0060647033cd004a5dbef9334eb35300b1a4c20653292bc158a68f927b4b293b31e0a46ea233f7fe5efddc0a32ed2a9f7f65e7e580f0d6b2d8eab1e9aaa99bfbeb3f3974038da8cd9eaa3ce6fe7839f01a00644d567f9d1014eda0f25219142c9a7ea5a4c75651990bfe6b3f8c9a42e7e1e3562d8f7dc1908e1e1566e2934c9543f8a1611b1178bc18bad5e6ee54e0b58421e4aed2b326aa8cce98922d9bbebbeb81f1b489478749a2db832a7dc1b66cf26d9ddb5a93e4101b7a079c2f346b56b574bd2b671130724492c1846f48966fbcd622c0a9573dcf8b38e23f0ea3657d8109fc0fecf0c2af0d99811a0fcfb91ded76e77f53e3115aa70c3707fb189cb2ef79147c92824a44fef264c3ccd2dd9ad5f6579ecd31bbf1d7845498774471562e32bdac680e921d1724efa309f7a27b50fe6a79340e3c3233058d217cdb5198038e453c95799f4190233af11dcc0a30e278296a5bdd59363e9984918f269f82d406bde068a41485a7ce12bdf46d96c5a7a3f520b8ddff164c2cff68304693668e82003c8426c90bdda59b9a05e8554a0f3de43da0e566d3654d2f8c678aa46c68f4100b7ff9ae8a0b91531decf712df84dc92b6f534aa7af3458b615951fcf1f443dc89ba853bcdffa5113806d73110dc9e8687593c0ceb1db1f66fbcaf03712e66ef52d7eb15b4be316f86997d1a1d5e8985eb146a3b5ecec7b439553f73369d5c14af3d8efbf7eecec97fc9ab32146f6a8e768e7838febf80ce9a6310eaaa221852b452eb79a667337c2b235e16baf3fdf06dc1d80c4a5fad1d71ea4e48a989f2937e43add52ba3ae85a81567dc671d8defc6b7fc7b5a91780ec669df6d36fef4f17b445e2a0b526a02700e3b1ee5cfe02446c7a49104b8b03825d0f9750e7b33cbd03b77c84e055da06434591bf681b018d7f1f238dbfe60ff2980adda3b605b374b8fbb6d45960fb569e8ad8406c355d02cc5df1590ecd20882bcc528f55958a51d41f2e7d0eb2138422cda96417f24e797f2cffc150665b91e152c1bda31775d204df9d10292ffa324589217377e296323dae8cd7315449798512f902d2746ae560b3eb0856b5ee8a78f25bc5649eb3943752f502a158df3b42d35733f064b7f87bbe430bb621821d589845fbccf5e099d20a34964dec203e2f9d4470c416d42a845eae107516db5ac3432aa416ed72369cf9cd73eb6e47142fe86af5b3a05bcfef58fb9044d31e7ee12ff7d86a5320174366b579d93621bd2755920b6d2b9920b9462db0f9efa3fcb808a7d98bb9308023bc19294a8142f68e871c435b4584271b775f601197a6bfa29ca4f75c48b8bdf7273d564f6903781dfc0034dce5fce973976712b9fadc91be6b190b6f95ed077630ca2cc9a9b7fda86207e2aa1539e4b8eb9a28b6feb489a8bf0077efd13e57d721eff489b2f7d90da52c47020d479eaec3e8fb6899d61f2859656d878d9fa6ec09424a9eb2bdc1cdd7e4ee23363b3e414782c6d5ec659da3c1f0f91238466b768ab8bbca32567883b0e5000000000000000000000000080b15202a30393f", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 32, - "comment": "signature that takes 10 iteration(s)", - "msg": "a200000000000000000000000000000000000000000000000000000000000000", - "sig": "2018db9b56ecbcceb5dc604039f912a0667eaaf3fb9d0027b813c893f1d4a62db7d7d952f9a33cd983cc346878b1fc80bca311bb78e206528a347a61cf2d40ef7537345b36bc09185f058adfbc403f766ab7cd621b1dcf044501d2e4596d03e9f69f52a38ff6e57e5fb1423b479da0ca146dcfa431437d10c6203e3a0045d55a9ed978734a71e5a3a08d767d9c0188a082f75a5bf2673f2c1d6d5a602ace4eb19cddb2750f5a06bccf3f485307dae509fa9474d02a112f3f9b2d635bebe7b18162999703460794c9e893cc464f57ee2c50875ec31e3e12261e37fed3369b50e29e531226be176d7b5453730852d83b6ad480bab228b7db04c32c03357e17a71266e25af128601b112e4f8498512a861a899a1fc59428d16285040f85e9f5f0f9804638885796ffd630cf747426d1aa46eb9833bcc67ad84f86596844798534b8ab0529b48d9cb8a1e26b57722f9fc2c1c93f13f0ae87c860fe7735a999e2658c872b66a8ccc43a7b82b38edb3c98529527cf63a1fd1bcc720de1f20935d69bca533901899a8616871f9a8ec64df0a471fc796cf475efc4cde44a619af0406505f4ffd7317a4f9f7df20a5604e4c9c7949392c6a09af6e813390e567bf65b8294adc5d498ef48112386bffd70f8629793b3a100c41fc9065b11235b26cb5f459ba3a25156057f53e4b6f9fe14a7da76e5df8768aced4deacdd37350ce2444476855ac2d68f046d881a8e154dc178d4003860e01eb76b9f3f77b1a272caa3ec0c09f3bce0fd3ed321713c51dcfc1450cc80e7e4401539c66f833c54a01f736967004b9a1514de2a34fdf11720d30b80d19b9be7622ea060971e6e9be3ef918a2bcfd0bbb0f26824cbb4317e77fa28252258b77a93b266ac583ec182c2fae2e574b14c44dcb6d9305862f279be5456cca1983a11c15a0e8b4fe1421a6e747e0babc9dd0c6e41f71243d09e6d2a3010c79efc80c519ecd87f07185f35801e9d486b345bc52dc7ee3f23b64128c49f9ba42e1fbd76c77f3e169bd2b2ab224088549d087cf3f9cfa6363828e665925ef607a1773cb753dc2b984f03fe148a8428ba74012ffc68d1023aca875bc9385657b0784ec5508c4c318e4f002471d7376e4a85870ff6bb434e00964ca8fbf2c3b8797f2c5973794b8f7bad1ffb400a62e2290a6c2b8dc767536ba9e9e5b13ec2476c4aeaaefffe847b641b1a3cb84b4acc7a4dcdf44c580d1665f7c9919368cd041dfbaeb17c5e7d7c307ac3894503b77824a8a2f98e9c78cd8160af5f871ce2fff1c56b4d394d7de2d5d8dab7b12973b80b9d8e4d5158fd30748f8875d5e7d0e95dd3ad2f0d8c9d4750b8b367079891e312ed2035266453a34d287c15476e38db30758d4b3454b8680a77aac1d78ad813db95e71a13e865a97e5b989179ce2a035c25f845585a220c820168d6feb19c3c047c0d79e520122c059fabc7a392a1a1e9bd64a23e061f4bcc6dd4a574ee2768e3081037bd5001c62cf18a3744529f4bc20a38ed7c567463457e293df2ec30fe08511caad0de51eb75cf9ad1a3f3c6983f8f13e7d1102e30c9ef34e18111a8cafed32c7b5f3761b12ae2c8008b42f2288a3e270b51cf91d5b93315e230f17a4852bc2458a6672c784827612278e4edc063d597fc74dcaaf7e3a2e534596336c4a59da515499b3ba5eacfb983fdf54812a08b2d7d57a16958d5b63d7292b0abba9f8282beae47521e08751a0ac465a56cbbcd6c1e3214c07053e63da5391a6287376ac4c591615d2b4ae291655521f0fc3ee383e74a56ea92017cd460f649652f0615386b6bff3072fa126e0438234c07678c2e7f889c3c2d5cb69ed3302e2816288e1956a45c2a1fe9832b055532833ac806ff672a12622e4d42daaeb84739f50e4962bfd22a9a45196f3aa0070ea51c328fd7a4a0827f08f938b762d0efb0efdc331a2308a4b2d9dc6a7fa1f44d76f0f35c76ddfa7a4f2f4fcaa5f71f9bb786251858ed36ae275c90a30adfcc3e6ffacf06546b52ab1b95061daf0beca722db7cb435813000e1710b40272013c70634727511a6674bea6a0eb14b8fdc0142d2fd2daf2d0ba36576babf762a31b034475d1a4c2a947575a1141bd5f776f5f94c140a6d31e487c04c66025b089239fcd0b96bd302fdf35321a26c1c0074d53a83ea173ebb060b48a955fe929cf678b4b36c4bd250c2de3aa1ffc00fac25e7e0cba4cc481c5f427c4472bcd58922ffd8fa2678b44df43a3257931ddca820f8e98937db8c7a93b3aeaf2093ce21fa6867ffa1fd0fe514f5efda475845a10e38bba014ec6c436bdd7771fc65ced9461de45f8dcd154e2b09e64e568a84fcd4421c5a07c73dcdebd150543ef2936bf8e79aa9b78171fddfbee03f5ef00f220c7acc9d4e422f93bddd6516482b035455302393485188fc3929812ae0c8cd995faa2105a5f2bc1e0c52b463f4fd12f7e205734774fbfb7fb90a7446e72193b603db5e5fde3fd33cd18807e5c996bb8d9c29ff6abdbc0bbf9de29906c133096d1067787a00b769d61882d6844949b61408563344dd5062514d4ab73399f711fcfc4a564a8dfb226d06acb32c3c1cec70cb5017aaec91d993967857b3f639136d7045d95a0aeff60a586e735ef6053e8dd7d39288cd422e62e5098be38798cc5fdffdb58f5da0fff6b2e161e0dcc48532e94bb4315db65f1c50234643d5ab5334b72b6d4bb91ef89216fb85e4ba8fa3b01870590af958aec47ead6214a7cbe4ca0969a9cbc6686c99a8df8f0b45f1fa22661be59df11b067adc74de7108f8ebf4a6a640950a6a736eccf2ba0ea569387d56ebe3b8fa76d073f10df2cef5c66415d36e9f0ac4b7969d5f2290c065847754b610fc4b61525d9cb272cbdfb0d5f88a8d77f6a83a3fcf089db51346ba8cdc56a900ff5a377336730f0a1cc3eab86d858c4b91a12ee67d3b91b68fc50b367436a1854d4a979b9cc856ae2274c11bea5679a7cb4bf7199bc3abee35eb1361f0099655f7249f0a1713be3991db58ebb935f4d7eede108c03785141505ed14aa6029f567911fff5a5628bfd8f0cdab94c513f0593f919af896005f101fd75d98122635136ba64de10a74c9482bab40e9ee1ec67f403db7baf1d719102b0984b803e2d887ec637f4314438d615c7a2195ffd8b8708519812df46d1b358f65db01dcecd360380237200f64e66e1a96e2e2c67d548ce1f221a4746c66d2368122fd89a69c06fb7030db1e12043f51d9aff5cf47c489f6e6804087629c76cb6cb48252002571c27b951a544d5197a1a91853c47870c0956e9b1a255538fb961c26360f8e37ce46fc9e4d2acc5c17f2970ebb8e2aadd0aa2290cc80b3a851262bcdbc634bd8d6162bdd196f2bbaa5143ccf248e83e112c28ba4db148ffd9372d961b6cbc0627b409f4faca3d55edad62f0bd06158b17736d31b100d9b24378a9babf0ea6e0e9e903ce8c0d23270e0599d42e489b34b17aae8088ec7d769591b4c61b58559cb4bf01db99cfc4b53c9fac5e6e004d6995a3cb75e2400c25c01370f9d77fb6770e61a4f52869025ac1229acc0ab404cc51f9ab0743b4522d15c1ba584e4fda2a0d189d0063421e73e9d60be42eb4d1a16147d928f4931bdd15df9112f39d14d0d1fd739b1db56ba798dfd38b393e4e9f87fd38c24c595f2fc8f25ac1d8da9a4c1d1e2492f5eb5f3c358da0da8d2b1950540b3091ba455da3c816af6fa2b3f2211660c0817e3922b0e446b16f553958128cf0ca69a3790d204a41baafcc4c5e0bbcc502c9e986e08b1076ec32d42d44f7264ecb5581664fd76f2a3a2ed87acb8bf2b18fa962e1628a6bf2c75e3347438881d2bb3a36551f3920c57e79d896dae9e3ec8b4a6f4e581d185fb72a6c772376f6f72298ae86c12f518ba6131df075777b4c183db7217913343b6dfcf7087a3b7a4592d60fb616d446da2892664da47bd41d089d42c5db3a7fcee88b57f13201cbe811832a998ffe931ac2c970f949b668fe7badfc67c88ddfab37a9fe6b663ed5d10d8b418e8831e894f7baab68890160daff92580647293acc67e9c27ded048df2145fba9cd6fe52dd60bd4e734639e58ef7f136a727e34780cb9e6d5390c3cbcc64b61b19444a1d1a688e6b8d0c6e2cfd0c7edbf8f320c65b25c022bf52db4cd5abab21d5d769572d827bee49c5a568821b16286bb38624d8ef048e1823825a3a44d013c6d5a31c5d56ec85be1739e669993eea4ae66b0e54fce13c30a634dfc4a24d0b028e1544bf5c9e50f74947c94584ec16d921b2aed7b72f1543733af47f7d785f3233d818e20a0ac013c7afe2a4eff7b5a67c3eaabc6d16bfd61960483198952d128581b29e426bee2ef05362a663b84b4d2d8f86639abfb0bcd43e151daabf617ead56384242ae1ac24fddc27cf7a35c1107339da0b50991641daa71dbd500a9041537bb299cb5b681eb8190badbad025fcda8f2c598ad093b87abb0456fd5f928c6ec2196f817668cdd5f47b52e223d2c5d7de960256f79590558bacc0848eef0dc4995a6a337442e42d8b9c25376c73122c754341066622bc6041819f59ba8e26d73feb31903ffbc4feea883c01fef5b566047fd3470fac9128e69ad5ad42c24519d6f42612d7dee629cec64e47c6588489500844e52f977f3304c66eb142b06cdd8e86e8175e79a53746f027de9b9fbb591d51e70a3e7d1b5a4807df7f80f691493c6632d171e4fdcdd4baf3ec12c8e68855405fd9fda6308fdea9997301bf0e99ea15409b0b52f8b73570f2f9f31f3d0975842c72fc7a738939c12cfc16c6a8c2320add187cf6f69782e374533dcd90719221bda2dc93bd7c3c0b0389e69b1d9d77a731bbf989f09005cc6e3cf2e1e6a15956f5d890ff32a6456cd2ea0b5d5c8395cb1c4d1b866feb3e623cba7b69d8d73705fb4d80c341219f40f3b5db8c573a580f8db4e09febbcd3776d61f91eb83dd786165fd109571497e34347a4b1754106c0eb2c8a008b3cc7bf8d78dac9b4f1ff4392159ecba9a9b8374d5dc21b0fd2727dc7c3e30b28209c6e98df83a63ba004ff08045675718af36bc138639fe11a03a2e3dd70010b4eee3e505d54e11b72764eb325a3f37bbe53ea43045f56fa7b6a44a61eadbc18972b44844c9c67af6fbf48554a0160f3c133cf92e61bae68a2082afd7fb146f71c96204bdf91768bb7febc9f8a1b6de5f18e1487097073f1d09811eeb5b95931c55fa8195428cceb67825757a2d3b3a1da8548614f4a1a9f561fd2e94cb7737d6179a99105a2a5b810a3639f9d4bbf0d0cacca5609b570cd26e44cb9ad2b693c3558a7055b6ad00407d883cafb55a8f8bcdd26587c3897fd69a003981ea9e8e650d0730a633d259eef78796318bde9e580965c2b4ac17781666ee0e8d1d08d2962ab4583428f37a49a3438b7e859508f744774f68356c90f75a7d1ef490cb1aa515eac2e9f0862c15a52fbff59af3aeeda72082818b88ba7e21570b13d564dee9f91f2cc57b1b109b777aa4bc24c884c6e12a93fdaeead08906da35d1b2588d56435423251a10ee9fc5fc77c89dce3e4498a34ccd3bd5ce24db56be6810672203c5ef9b60b98884f6e858ec9ba5e5d0771ea7874a8075dde2a6d18de0daff94bab62014827bae60d2c2bc5c2fb30c90c44a3b32d5c047e244540d9dd18cca729aa0384dfb150fd07aef9aba1d703088e9eb458d3410fb8bb076661576a206549b95fd6b010e54206701dd2e7d42626fddc435c34cd92b43ba26a2ce384ee8f3db9795b7aa5ba602cc60d275f5b8eedd2b519c36e42beaed3508ae4951c6787a52487a98473b1136879858987a306a573c44fb296e91c59a5fcc179cf45c15a757a20a40c0f03b32e25047331b61fb8a8b91973d8fb8d43c1f23ce6067e24314ed3ced2e10f7a372acd876653acb1d97abd679b3f0607cc6f487720e2de53375982cbf8e2afbd5630ea4d1a97388b41361f6fa47c51f7995b3d5d5391c20687f7c8064accaa302c445fcdc2be7c55bade571b8a211a1b384e49cf772e0d09b58589e9e1c3489878db626ccf754aed9cf18cbd64e94c67e12e89e6ce111c1a740900f1a91ba930ba8adea40c0b9c46ca88546246551a06caa68867837c736f9a4fdac30a04b7b95f26ecdc995dbfad1fd9accd3420bb7927124336a110ed85050c9205b227dcdddc59db93459a71f7b7081f34c98776fcf8660e2fa9504348e35df6fc52b1349056aef39431fa81ac6bbebbc63e95b692c6c9b9570afb5df6cda1a269795df5ce5a8b32f9974f50ff55df4fecb8663681933ff808624a28fbf501b2cb32b05f86ffb7648dee35bb1df7b06292bb8a4a0fb87bffb28a7598f979e14613e6da1b17c555395121f61aaccf65829fa06e5ca68e9a1a15c971e0a796f214bab43e8de543c579417956424251cd2f2380682dbcb62e4074b9c4c505144d4e9093b3c3ed0f576a98b1c7e7071d206886b7ca313257808b92da00060b164c6229612558797faab1cf000000000000000000000000000000000000000000000000060f161d242a2c33", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 33, - "comment": "signature that takes 11 iteration(s)", - "msg": "3e00000000000000000000000000000000000000000000000000000000000000", - "sig": "2e3ca5ce99cb54e65ced1605d302878ed61b0dc9ce7f3d6b08268805740de8a44f5aead5ae063a3914eccfa75c2626c3bbb5176d59083206f4d18c9945e00fc2793e4c262e139a39f92e4e5ee9cff174c99fcb5f4216d9d2174c1383f920723e3c51c7c99d7250b6226d46307bea3aa7eb8cd25c0c6295fdcb0c293b73fb22e01078c3e6e2f2b0b3d55f10572a141a3a4f45068d0e44c3020d8ff9546d768168761a00734c3bf14060f39cd207290858033d2ebafe200421e798ca2e2f0ebcf3322f89e79ce64b04af9078a4c11fa1cc83119fdb49b30598ac9bfb2add16460273f23c3b12d85f0b8e07451a0a700e7ebd425b9f6db8e15db820a21e3b94d967e03c2a2d0aa2a0375e1cc1c8bc16bcb43e4c3f29b9e74d61f615984d83c8fb7870b8b9b5aaf029aeea0c5ca526772827ad3fa0a199262a368074bce4dd53c1fc75259a86095f6e7f120648d808221677c970cc73d17aec2d1b52963d5b19ad975cad4fb687a2869a5131585e8995bffd971b3b256cd1a2d6c675f8e0cde1f49ed34a2948d8afec3250605663787c1885ef8055f9bb854814168debd3bfdf32a0208a07f4ca152998ca83707b0c4e5fc83a0b2c3e7f48142b6207c32118ad450979370cfd7dee6ed7bcec25b14c75606f02314d6d6c1939d8858b3b684e118225edb9fa647244f61a4ccfc3c28be91ce969dcdea0ded2c85e42ebaf2c3c13e49adcc9ee07fd076618240b901810f7e500693ede04ebf166834cc1d3498c36fbc9d541f8e96568bfab56b304ea469d2e762366c3fbd1603d031671576ee783c7e6d56f2e5388ada9ff69895523e9bf38b2a7736a153c2df02f948c27f10b995286041a2ad6d86b93c7d8f23208bfc49f1ac347116ebf15e00906419b4badc45a765af05fc267ef960b40edeaf83d58d08a0a8554aa1a0aea6bfc52aed140b84e68fc819837dc1f65b773d4dfd83a7589985cda2b05ccdbfde770e9db1c3607572e7be52a0640b74d0f990047c4e97f3f7082ef9ce3a7193b2895347f1e77908ed0a0fd60ada14d43d7d1878251998caaab08c92c0e3b3f2e8d9f6f931b9d8133db704eddeb73958b2bf98b221e0ab04ca314eb443e7471a8e0ffd4dbeccfc1d71ae375e0ca25911215755db497e90d83c3661f60c189961c6b3bb3dbb8b35cbb88b7db869388ef581bda329e5c572ebe6691e71a118b5ab6229f5cd1748fdcc807c5ffcd057fd61c57661227e6cc62532bdf02ad9fd052f7b75b022cef3cf260688e055433ee6949dbef4cdd5832a19dd90719852dffc5448c3a910f52127596494901497527afc24278a54ae224e02ea489a818ae486ddb07d0bdc70dccba125048ae50b5318ea099b7195e93b4409806a1b90ab8ad8d4ec9b4359b713cac3f05b916268949d65865d9da43f1ed7007f387a92110c01ef59c511e009d8b4b41030e5e16903f72071fa04282827176fe2b8f2d7aa19fb547a7d286d950bfa4641be0f594a1eef5d59c5856c35f5ecfb3f12177bddb3b17752378bbfde1c7402dc3cc0bc80850118442b7e0b5975bbfdd8af4b1ab7ac43f0aca01bf41d61da0b66e0a1ef3a82ef1c75272905ee29e1c4e357f7d2afa650cd118d6a84e2f0b4ff8a90bf2021ff33254642257097da4e3cea80e729873871b278aa615398f338b361ac8624620a1a53f00a7d692e1683b0c4bb51f42252958ba743355fa695a3f62dd6cb1db87f0aa1b41eef972b6a0125458046b85fe066345e85c4e39973bfcb2ff9346545953103665d9a0e660b590f0c57a3af9637407467752922eb01eebdffbac65e1ac5553223c59589f51f9d7021183772713e173c56add6fdc7f47219ba90f87e3b65642aa5a93ea2de71bfa992ccefab80cd4b7dffad3a692c5e9ba4817a6a7b8db8b3204d7aac8f027350033fe2ac7c3e12325a8d71820933f67dcb06f2f2095165e9be9f8f38a3df54a6360d6976aba7922b3d3170e4dcc594d771854e6bfb676b2d7785bb3899f9b19a863257d23b753b60cd4106fe61484a86924b7c4069506eb073279d23c3739b071a0094a8a64dd9eedd8b2b2a338fa1c4768bd1f93508afa7ff5cc647b2242e251a9ea43560a01a631ceb04ef51ad2456b99fdd16a6369ef9d7a8590217896c797f3d2de08572f26f9787145006e12f50d19758a4778fe64d34a9b8b8a5729c41f4bd60e4c302274138686e0fb1e4121f66437aa2e7e29ea38d2170214363196a6d9ec26b89ce164198f70abe203958e2778c9d7021bdea695c51fa5544ef4125eea3540e265bd08c2b6e1244760bc5db2c5cb2533bb595aaf0bc3ee1c1631ffcdfe3e4c39e72af380294354886ed138ed9291b9d18dc02605a01533dd526448aa059ec6d5e814cbca276bebc3e34f8b54c8bb9fb9e8b188e96871ab7f2417eac7fba8690a77802e205b2de37ba127e2735741f1b10678937a89448429439f701cea78407fac0d7133f19eb6a292fdc4dc4f05b6c3c2f04de7b5128ff4305058b06c03e1062a69c43b2f0ca1b181914e1d6f174d9bd18400c7bbd3658783fed0c608addddaaaddcf8b4d1e856f5eac04c1b8e6de8456f2096b392911a409cef4a5d43fea2ceab17896b4a598415befeb2de7f275e9d531719fb1393c332c9aee8b7e226b0630ce4b7c7668a4c0ad6b677122017b520476508131c1594256d0e9a8f43633ec6d957493c858d1d00d7670cadf500efdec6697967bab072d9915923e124340ee83d60432251d8bac3cf43b05bfeed699d6b199e0af1e403bd1d0e5337230044978dd826a0bb04ed6131727dcdeba0dae8f9d92d901a7909fcf9ce546b1977af0c4adb82cf76c2603ebfb4b594412f180ce77eca5dd58fe38ecda976751606dcaf3a8925cbb8df2726e3d6e1fefa65dc572c09d08b147d28a8b352855a36bbc573c9d88f42cfabddbbbde5c094c738ac0b1abf1167f7e754dd7e41058f22d662cb942c84e80bc5176390bfa34421d18ef744fbd5d7875664ae3e307cf2a8f77448620a20be6b2687b3b46895fbb15984a2eee5767c16944b64d7fdfad316ced9ce1cdc2499432a37e7a4d0a226713ba625758f164d610a0f7f4b922ecf70ff1124cb354627ac5118643328146ae5109896fde3e92950b6be6d11585816c131121b40b648223d7d8dc08723a36181641b7c7377280c566a4e01cdbab2a675ea4de796398ae658d2c248d22bfaf7696cbacd84edeb3570e451ff56956e5711f65dcabac96e843e76e26698edd0726a4494acdaf3b78466a1e95baf096a1c39f0d05a0b38046cc8a802b3adc74714357017c95fe124b9a0e9f6cef4d7ee64ab81b48c857f7de507057bcf2b5de6a436e4f78ce4d6be31d3c8fc7c782a7f876f483fc3c504c85b7a615c3ff21f251feb3fb16f12e899b94b9c6830cd942a5fd6ec09007206c7bed46067154ed632a0b049db98af3a3c33ed71f3a36c52fe21f5dd4660d668e37afaa87bfd08c5f5500ce639c0742b9978587cacd521a1554da3005619fba4e577fbc057c5d34c70d33bb537d40568dbca9c2ff60832889150fcbce07df47431a5b72ea5f7eba3ad1c9d7d4a9638ce57e492c189b0805357da10126dc4d994a7a4f24f9bc823f30df362a82aa15ee662903d5b5600e1620fd3cd60e625ef32734d6f65a395292b99be282766b7ae43d8328aa60fdb2b4bafe0e9e7a0fb176902c05d77712c24c9046286183dd7515bb50b1d719557f6b8c75a17e1875c17be5d74a2ee99539cac3963ee8157918541952e3f7232b400e7fb2476dbbbd707c0bf14d3b4935381d5e32755041befe0ccaa57af27845f8caea17e6e2bc1b32743a79f6602fa2207b0d2f0bb03af9283eac9d5ff24771f8b336217766f65ff2809af03c4ae05ddc313a79d3cc22c5720c5540dbed7ea2b8383719776130f9b0ef11a2e3bebbe4d8dfdd1c9723abeeb5f12870a119db933829064fcc53f3480751a49a361c56be461096e7446d53c018d9e94e67207cf63f50a103c59e075add0578662e8640d5e94aa6fc6e7de6b31fe3c512666298c67429fcaf0668c8d3f2de0193bbea158860c89df422d98b50261f8a8b8692802867f287604903373e4f093f2d98e6149a00dd99003c30da9740b141fdb7ceeddaca9ab15ea545fe4cb0700e739a894ea776f541313da6d47fbc9ae601cc9f2c2c26a084e1a1b5371057873982436f8201ddb8f427bff316b20f104100f14d9dcc036407d9ecd4173de9865d9f87fff4eff7bafa21c291750900bf7e2ee721fab2a64155b78de81fafc354ee2abe285179fe597a3ce2ecd14b1d2cceb6e4220a5542fac0363d2628fa43eb01bc50a5bf6c30bb54f375169a8995ea6ad24bcf265e1b31e54b638121447c0e2d6c9865e52fd7f95c93c7178ce728154af72e92c5465b6a9307887f26ef16a0eff1d216a4eacc47f835a5a9bb22e65cfc2f3b46d2e70de4e310eed79445249fda028668ddd9421e5f3c4f94977443a90afb6d7e120d5344f8ef8e414a808a59243011af2104a503a968f9e82cd1fac355661e74f34c03020c0eb4e02ad6d3e6cb505c89150d5eb6f1644d9f4fbf76f6d682daeb400372b45d4175b5ea0873d65a39500f40c5d0129658fb97e241b7c93d597a9e9c355ee2c379c620e7f6eff73fd95a40033582bb7c3798d289b8994d61ea77680965c83ff39e641704754d6d7f1e18e5ebd3af05c28292edf2f731c4038c342d7d026e2362a4dcde25b571b0ccb161a1a0ea39ddf92c38b092f81ba3af80af7cac9622fe9b7c78d7cb3b40162f69d8f31e8e1af9cbea28456a8fb30931703f63ce4ce0a043d926f57acecc6bb953194498202c6b3e86e92ffdc544920646c4c0ed3717ab889e12c255b858e7d8017055ea5e9704d53aa3d71568fb6988a4165799f1de9373ee2534d63ffa30e5e0a64ee0c3397be8fd5e6ebffe671c658eed4391cffa17d0b561cbeac7829b69948c61ec9ad95f390f7befc6154e29f7e58516ea38ada3b97b9b13ac904bbf4f1dc7443b9c2e3706b7339026dfb73fe3d4d0fcfb1a8dca175602ed8ec6bd2edf8f68f12aa10fe159de737260f4bdc0b62561aa4bf433b3319720214177a40d4957ff33254c9af97134a6222b04edace8f32f6e5fb9b9820cc9e494b49609d57735f4d5f22da47fbbf1cd355f2816c8fb50227054dca96970f5b8c77e32e78b23dfa974bec354ba7510c746a31357d59753bab0f26244f23a9fd4e9498203e135bd118e517bb51abb7bd68054b63c70924405a7118275d4f18934db3e10e7a9319202fea3d1bb4b04632f888704c7830c9b79e0a1c6828fb9c8708ed710d9cdf59e8319988612390c9607d5ab72878a433938d53e7bcbbd94d1ac1b4d023665b8fa072bdeb18edcf784739232ca4bc028db22abb45469ff85cc615136efad3b08493570dab2cad3c1f952f3076edd281e319bdfa2823df8b3c5d622e51ce602c3ac2fdcaa6c0104e893f15ee2d72f399a3de7793150b1ab38e2eb7ed4f25abafa680af7299c3168952984cdb5fc7e983e409d9ac8a4c8a88c20f0e44309f443d70c4c1ea6c0962c12607569de92dbb50436776a6959687216af651e719a44685ec3f40676a23b44ca93948bf0df62673c43b76a7b18765d68039620f18da5fe88f7fc55a22dd61d774a318aaaf9a8409d6fe7f28dffbcfe4ce250ca692ebefd03fbeee73a484d6d91b4c0d33be1f8a5c8a8804de48f58b8916ef107294502b3b0e1770f922640912efef57369a0a5ca1a86a04aa8c38b1bd0da3ae94611ced98494d704f8cb05a183dc5991b13b3167f3af18a7baf2d9feeb061f3e02d62c482bd8fdfcd20ae27a729ab64fc706eefb4686ecd2324b48d3e66d6585bf026a2411248370062dcd91e61ef6ec39784b4cb93bb3939c19bb68ea0bd6416dc973031adbd0fc423472749d5c2ac67401e1a072983ccf11b53ccc64f3f1debc7a68211d9ae88febece692ecd04a305522579df0c74848ab4579b01ab77b190ce2b3d6349798a0a461a4874dc4e32528d6ac336bb18ef0ceedab6865131c5bf76dff1469ef0feba5857c056a0ad342e32c7e958af57aa217ad7726a5275321773cea28ed4e42d808b6eb4bd7434cff00aab031fd483e0e1d587c8fb5a99709853261b5ee1024a9c5ec483d06d902fd92768711a6dd939a8e912bf1dd2bdc6baf8d10736ec11385cf5878bfab93a04bb9d104ddbfcdabd5602ff7fdcca472609045aeb25571d970696746cc15edafc71bdd7697ef6acbb2d5c8d5ded19f91231eff487b582f80714f1ce92ff6fa5e3c2a5ca2dbb734c01ffbeecc38043456b4f43cd8967436ebba6570cc1872aea2b770a8f23326c7a55eed899bf27695d9f7700bcfe97d4fcf1ea80495c9542d08acb274716562b1790d7b308bb28b38ce540558e47ae199eef3232e301567b07262161a42c32745a4e6ea3a4d5a8da0a1ca0b0f1b282a5759a0abc0d7e2e500203a72a4a6e84a4f609da1e9f33f77a9fad70000000000000000000000000000000000000000000000000000000409101d242b2f30", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 34, - "comment": "signature that takes 12 iteration(s)", - "msg": "2e00000000000000000000000000000000000000000000000000000000000000", - "sig": "edf3ae3cf303fec3cd86b0bd06b7553201654ac09decdac7a0c20509e6e0f225ae64c697e41fdd1721473b00060fa1a831c5db520f5d93d54f7dd0a4659c45e3572f0c0df37d6b0eca30dc4ded4e7fc2a352f96b1828a52fe9a57b30e5bf29f8e1919208a6d557ac8ae34c6c3579638d3836d91061b87cfc1e97ef77919515e9ecb56a59632bd442eb209fc4a3c0b1fdc2d66d12c548d997dacf79aec91f3ae6961b1b2fca94c6d9264af305f0138f95595b55d1abd6b583be60b6a5dab1862ece44a04dc441959b8f45e61e041122842b99a01da8bf5cf3296bceba1e714928533a2f9e06c3d68f1b641d5d4dded2993db00882e0b5d8ff75143c4df9f07489a61eab6ea3b6a303930f441985cb126aa68566b7a0b162b5ab7a2ea77dc6a8db491b1ff3b054ef151e6434c61ccb3f51c1c9a20ba5f1b01d506f554cb77d3628a5a75a8e51efef6be057115a4fa8a6905224ce760bb7af76444204c19ae2b2f243ebe6f831ee593e92cebacb15af1fddcecf83da5059d289cb8aa3133eafda1dfa39b9b89b6fcf384f0963bd02be6b79f894c5ed4a754b1d8916cd428b57813e574dbe657a5ca8647a987123bc3c8aa38702f04189ae0aada16a6907ecde61c875102e0ff03a61bc42c126ff8bea094b4db05837ba9c05876e821acfc12b1f2ab9b8b65b4f4f641afbb4adff982941c123bff997fa681189545b2c776755baabe057cc04e4a6103e638be5b72d8e9158f93905ca7e48d5375c74faea8f58fc3e7e08b1a508cdf523b7efdcad84131a68d14ec15e7c7411cfb5c215c4cc1d6620f5f0afa969ada15f09e1ed1f938d671665c5384e6a4d38f464f5e8b380d35da2cfc20f0c34e39faf61b7530368627ff0d79294bfc83a8b5c92864da9d2a32fe389e53f42a8f346082cc8daba856eb8cc24dc4d26c42c5c5ecc778b6588c8832601e1765a07dd6eae525f42a5ec370540652909936f001fdad7a3975f237a3fb3803f4862b733c1807b857f38f853a267ef7812455d3f42953681ed95becebd49b1bfd745de75c95ee9e206d7fb700455c3f99138640885143e517480ce8a4de85e8860a8244ea14f646fc1e6f2ad4b1268b99582dafb8ac6b058dbe0c80161e1aa2125fee6948db424b503e77ee6136651344b50943d5121b65c21130e7a812a489ddd145b273264054da7d456333d53f48434bf168dd55638640a8fdc65724d933b5b570bd4994c63f968b55ea1a929bf53225cf33a186ebfb05ee615b550d08945f275cb9645d24990bc4c0c170d4afdf9fa02ed929f469f64e1aaccbdc559d438c0f7c4ce6d001d268f2a19aca6f3c7c08e55a95e1741dc7d1ff00f6fbe5bea02a279a87c0bb67356ef3aee69902769510039d03a09a3bed6f4385ad905848d107319d18df34013181297614dbe6526ded56d6c308e25fc569d68b37d30875759f7860e966fc0903b16b01d287799aa7310e80f8a3ea6df0f5db2b2b3aab9657c226beb030e1f3cf0c6c1d8ff94622ce4bd8ac323df1a55e5f62470dbec9d993e5f27643069b901a585a34b6545b995ac646bd3f6883a6a46a678bbd8436f0b31c17fd85a40ebc8252fd289f8e9c3ff9bab020c0d47c7d20e0ffeccd2bbc76ff11e625c670aa17214493dc2bee4580719d21b57e4f2acc7d9c718cb808e395e57d12a3ea344e70703c6ebeb8dd84472871205ab27495b029d632b4b849e76de61fc12d996e033f4fef8761151062fdee53044725f93c7796707aae17f51a9975a36f0ddb17e7e351f81da3d5d741688a9701586486f8e77d04a1c249f95526050024c9d77a7b2df351faacf34ba29570b6a01c16c2e3f7f0f5e293f14db848e22a1dd1050c2f7ee05eb5ae69f2effebea1245bffccbea8fffdb7833ec402ee9bad6cb6ea4f5d31d160127b9c38e2666da171be52b7abd8492d13fac6047102708936f88cd798751fe40f1a18228a053de9f49d21c0314a6640f0ade9db6a25b2c9b00e94d90b7540d517a52364b6acdd566603fa7970dc9995733ad9b26ef11f0d71a83b2aee94293c9e89dbb1a74711bb81a38262e697a75b0e2b47eeb9d06dfe491feba48df9780686f6f23c03eaad54f8347c552dbf91de7ef2a57518995980991bce9502fa3800e078044265e8ad49979e075e998f5a21ecee8adc091cd32fbc1e8f8a9985b6668f6caf9536dd0f2c022a4ec36e84d088148571c7826fe68820ace100aaa56ffe4fc9ead0c06b7d31026ebaff7fb3ef8ea3c09d2139ed2b7cc0cf051a0c021c42f82b1da2508af8cc76926db1eebec211ca368164dde40954e59803bad0454412725954e99f340058476cdb976653535050b137a1a4dfbeb0488c905b7f393a9564e500096722f7ca7c313ceb24c0901ec265c8396f269b6e3cdbbd5c8732ae79f9a72147f8c2c3fd7dc50b5e594958c5125db6be08ed53adb47bf1e22c883937b89115614086fdd5126ac7c5c53ee3097db40eb5f2c7d3fcbe7b8d1e10765f6361196bb69d68a6d9b69459efb058c1d56d15c0749e0022c377801b51beac709848e9b4faae52d10a1103a4a430455fd89f6df0acf1f59eafb2e1aa00bdf3991b78694a6e0f63cd658b63ec352ce0917d4aacc434e19a96e56614e220badd3d742c0cbbc564de9509a598b0caae6f574e93ae25f033169cc4fa0751c668cb318239095ad8a449270fcf14ed2c930ea9f3f0be65fa94622ee1f2833522a2a886d4dccfebba0bd6d3f49b7bf016d9d29f65d62c902db909926b1d18e08d6edd371d09292eb58a7c60b678d826af2f14a7352c94d31234243a9807893e891976d8151de76437240c3b27642bc19b35203970fb4f553aef29a8ff17e0c4f38f7c533fce76f7ab1d9cac72c81dc04ce97964d220694337f77692b3c63315db80a434138cee8cc516695eb02b1085f9c13521edb1399fd54e39ac155535fd872b4a837dcf1cd12ee3ce46abe7f3956cda1b4d8333dd0d23195d12bbc020455125aa491e385c88622094bfe7ef074998f0b7661c56b0ad50654da83a4342b3da5da11614377087ebb253aeac775be4558835bbc37722783df1f0611dfb1ccf0661a6e72e2b4339f7935be50859128e26573e172afea1d2d8b09e5b5812b97999e300c86dc78d3c009286272e8b0ddd06b7abc03e629d37e8e60dcd20ddf4e9d5dd95eec990a027857c628c7d94cdbed10b417de8c95c9b0cbdef9ca7f1f654047ee0ec9802907950d1f6ae3cc9288d9a8658f250b4a01301752e20b1a3a42fe918f1953df8632de1dd77e04a50bcfc671a7bae509a425730d5e74b7b02245cd84fadae7ab8d9da51535cba79312da56a1130f5c7831a036547d15b1256655c070c7db72747f7e50c8389351b8d0516b107a3fba23c9655ac4ee5a1fe3fc2a6618451c14f6076ad04782450248227c14ca7082455b2d86a337421dccf40e6317e14d6a52372628b50aee6ecf801dd253a0cfe9a0bc9c34140e3ad9067a1303e2572e66a65ba8a96d4354549153f4d4f53417f51e7ef025dc032e687f953b227f13352208838ce4dd4e69a3094e0988f8c1c79c31b643b2577f7d68e82451f4b75827f99a67f9401ec52329327a76ab63c68185b73e5ff00f93ab50ee976356e1c06713af15b6398b814498913f824a186a3ae6d788bf6ae49df4914866ac9cbacc8b545838e4b90457c421057c1964718a42050e0a5725c931875e3794d493f947a9a3fcec5b93fc7f4d33ba48f9bf15d0fc9c8491233523ae4f0bc9eb3318da578004404fce801361bb4c22edde80bd8b309c9cee1e6814e075ba5b2fd4b17f5c20846f526caa4b769f64c12cc680289a31ddffb3a96fce6b50bce38f623be8b14cadc39386bdd8c38c1ab7a43e3dab6905988b6faa0bfcba842c23a71c06374c0c5d06adaa73c3f2b096cd8f285e8719df7205bdac128b7467fa5f393254e541213621c51b943f5d99d4e19730c28723f3381142f0f78973f8245c4eef2d695dddf0077495bff71bd26998fa4b4928dba5e9caa2b1f3e33901bea01436656ff6ad2732060328e88027cbc9c7d911a4f4fa130bf3136ea167166ee5942ff8c37b649b378b185c0137c06096a4536c7d2384f710ff4a811836189aff326216ff019c04d02303ce2109b33e2e007eff39be4a3f75bf2193472d16f149d0405b04b6399429b3b801173ea65cf042ca18080ba05422cef6b8d63dea9e6aa1493faaf17e75ac68a3ba74d8f0ea75bd917253d7e299024191ff0113fd7953fc216eb2d9c887662978cd159e6c5d1fe6ee9a8382a31c1a94018db8b3aeba95d0a5ebbb22f470fb0ef35ff92cc5bd88b370c6e74a1ffddba1c9a7fb4f8e315237f77135b18dbbdd48d2c603a3ea51a40fe9504d6a27a288324596c9df55d8b68a564914657043e3c71f251c63395b5203f6364bb9e0b34244340ea54cbf0ff4f4d1a91e378a8eff31fb185d869d3b1ee01949741a2395a3343e533041a2f76a2c88705366d9a469f7075412fba27e50058942ddabbe27c19406cc549b3b7633ccf8db7a0de7e5ca359455d1528affca47f3538d65f22fc2bc104199be6422ed5e7e20edd40df5fbd0c707dc71fd35e85d74c21d908fe3d213736b7968c6c86b0e064ad68a7d098acccee868c1518b7b99eb03b514ea8f62196d35acedbc3c0efccdf2d3fdb791a089855392530801cd7c2bdc692484383208681a497c8f39715421a8abca67b500650bc60cfc3229c6923768c0af67eefa436d746fff024b8cad5c65f76bd7fb074553706c12bc7e903df4da807f90424b13106f647a7e034165c9fcbe0052a31f39c8b085d25943d9bb4173e568ea0a70b8997be3af0e62dc5914bd03c4ebc6d00dfbb14504bf108f3e3244396b933bdb59ffb603c1fe8b193c974baed119e96aed579de588d8cd8cbf392c6ebc32ab4206be3879cd43a8aebeff4b1aafcbbc0db0cc0c612358c236f5783b92ab623068e45aff8b0ac6f15db6fc36b98f57c7e947f8c6764979725ed58069eefe2d712e9ec71ecd7c55c790a5c426a654ee5719eec88a89b31a5367b3451a16a41c4ae28a1c34f8569b73440da7ba9ccd28fe0b5205bc7a56db14ae4ec7ba3f5a477851936b8a2284456d9fd579767b1dd5192e2e2b61141c6e5e2dbcd05008fe41f75f3f41be3f994c036e044891dbc3de101555bb288ac491f6118d81b5fc94301b822b5305c4e9bc04641e287362eb56b0085a380934368bd0e6fe09194a7d77a4f913fd87fdc8f15ad33aaacdd1012f84ee093bd275e2f7dd55e1c380320da34aabff84d593dd94cd518bc24128f010b381bce607f116d1022b7cb5163e64ff1f5135e1e77acbdefa4fdfb587befc0d47d27b0239038fa13fbe676302fc77944e559994f660277f00c3b04606c728322dace42c250251f3175178b45c1623efd211a36e9be25bc316cccbfefcfcb8b4722096d2ba33e77144decb094477191fbe547d7d2cd7030e92eecd9f75a0c3a3a696dd84bc30544201e2b5ab22c3f6df90e4992b4c2590e744fce1cc792b43368a80d1ff3c13a78b82275365409d7d579321f681b44a3c976e24d12a9357b223ae07605fd4df37dce8ebdf5abb8755076466ece8868d11d618075c79816cbcbcca8481544f18c36a9c084eae7fef4b79661523dd0fb3f0e752ed8932ded9651964b7eb6343fd62701574776b170e4e2bd03b6a2c729e927ce353721e1b1b61cac0238286f4b347de9796f0ff356ceb83b4a42726ff0e2d70a0595d48ffef471afb92c54e0871bd346096c23e543669f43ead97b1b5f51e4b4cd70c92dd0d1cbbe9ca7e0f0ba97a568542b8091ee7a2918777c3adf26d6b6b57b81dd621532b305b210b29421c5626c8df8807e7952b32fbfce2a25b2b4c65c3096065fbb8eda1e4a4a18e12dc70f8a8d8ea7f72f11a91e105b4d89b11b6f7f3a963fc0cdea967b4a16c8c87e789436e805eb353bba9b622cdd05e5c736cd1dd0a0218dcf98be9b89c9a6e7f006ccaab73181b45f8899f2d0d49b5086c08ac92f7250ea720df9c21fa0515972b2ee1d304d5c6df4c2380da4849394ffd00569765b6820b99bf2fd645168dd1638b1000302435a958b7367facb10f4620d06ea431e86b52fa63f9b01b9be4980e1bfd1649ca8bde5e726d576028405fab16a776d0488b7878dc1010c4786c8c24208692e5230e453c974827187a662e776fe08c487c0b664a3b2ad861ac426d7ffa95118d6f79835a926a5b5f55eff3b7f0212eb6711cc249c3004aea38b1e0d5fa76c426f1558e3834210aaadb29644f61565f0e481eed5639bb6c3d09d28a31b63b31cb1fe0d01324d43cd62d6ff1c9797e320207c1755e4de61df913d0f3101aa2ca985d891accbdd412b76a7fa6aaf442949e520e9d66fd94c1241530bb834d2aaae26c9d4f2a0085574ab9eebd20ede008115bef187ef802085196a5c7fe314a9bbcf102093e4c4e8ebdc5cff33149688d2b475b7bec062a74888bafb000000000000000000000000000000000000000000000000000000000000004070e131d21262d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 35, - "comment": "signature that takes 13 iteration(s)", - "msg": "9300000000000000000000000000000000000000000000000000000000000000", - "sig": "bf388e6fd3cf1167d6d339ae9dec3dd40df2ed76bfad703894b17ba80960091177035befdd4b663c05ddd0dc12a2e9c4625d854632486d84bed61bd38224768a331138c907e7fc32ed310b3fc0d4e0a03e9bcfc6ea26298a27c09c62d9b5fc6281dd6180dd91e76d4041639ca6e524bb422317a3c52ecf952cda094d8b9b3251ec1bada99f5dfa57eb681193e9c41c2e2a978335b119675a12ce5fb14b75569e886c8aac29bba354ebe3a9a0a926226ed197ecaa9ef5270af4c3c74d1105549a23a97dde10fe03add6a24a0922e9063a088561404abd167b503a1666a7a1311e2528593b42228c768f17c394f580f62e7a9849eb68a1653b7e1a8bcc8575d32dc547c8f83d26e0e87f5ee5baa9e6193d006a5b5c435158e8c2422c469868f5236812a140d5bd30c9b5c82a5100335a3322adea49cecbd84ef4351ad348c6cce0d5d542d4f3c4461fc2e237f80dbacad0f5048c06370f645d4531ecc88a23b60de06c0390576619a66126bc4a1477283077b809af2e8a69e2e2f8cb5bf465154ea883db31be972e8f163f6a70ac8a05b833c1aa8f0764dbf4515c1c943596e3a60241ec3346cb6294f80271efd500c08946ee757fc93aaf0fce2cd39f571bbeba29c0bac37d1ff132bae1a6dd434e0a7a831880e2cc6a3211faaec95abc3a7bd23635530b85c619200a8dc67c4c126b9a595045e0a8c1873e4df0a2c57f973b2639feed44d598037f7078060c85b463f7b71ba073167ea32e744597cf1397ae8f73972dea16c3aaa7ccdb12be07281558a96bfdabe16a5790b8cd6ec1fb6302ea9d1fbd3ce9f18acb5201aa4ca89dca2ca7eaa3b7ff3d0cd508c5798aff866309cd8676739b8c4afd1d042313b15991e4675b7c05ba5a2664da17924fb90f288b0716dfe7f8d1e41038a007a1f1040b5ee36dcac8ec3cf811bbb801304f279df6c1a407fcf056508c62d7a6dfd4142ac38d9099368798b26281909ed58d6b83264fc7e97fe7e621107840489910fe89323cfa6eca44e7d5931a6b7b688bb699078b3b8532a35a1119819a43c47dc5a00ba8e0626588cef241c572523a879c749c6887731f225922613fbaf2ca20bf6420e8f237ba466dae3425ed7a58c1b813cf1466634541a0fc0a02f79559ecf103a23c2820ebbfb9b3fb2d7c51acb901c11943badf56077cbf06a0e6373bee7da03f168f66ece8b1dcfe62cc26baa67d8305594e62080fbe031e67511d884a1b66ef9d5079d5d1dc8bdd80873b42e031c075150738bb6e9f049a0f571bc2756b7aabf675b99961af386d5539e8f3c58c6623d6a95592b967034fe7bd01aed85270842265adbc667c497efa9d14cf8aecac0f89eb8061e920b97d8d57da38fd2192c8764da75ac0b840584c8c762abbaaaf5a6107a47be94f97ecaff51410deb53739ca9e5be4bcfb889257b6cd032b845f49410572303ce7623b97571a7d13d2e6217d5eca0e2cceaa5e461f8f33b8504231f09eaf1e596086b55e17a7d51df2cd8e4d73effc1c7c430408182ed4455a346c00bd72a2ec5cda463106dfa3af998c18bd2e46772758edccc72ed76f4f14c4be378ec295e43eb1ba4c8edf1654c27832812dbb9e1835e7bbf817206867834cc0431fbb9c1572efb4f193575a5d830ec2cbcdbd7f3ea5dd80e2c51ecb4617f01a76767a44db55d9f7ebd1179309cc5491fd02a4922f4ef03dba1a21bb6a267952ca63f91c3d8bb10ecb679f72c1ff7466fb4886646255e114791c531f89fb8e3be8f134d4bcaa10cfef059821b8325d11c9c8cbaaf61425b534675281a37f161d1e7ca28367928628c9f828e1e7d3400a9b319af2b33eb5bdc8b09f7a13ec68c3d95121c97ae70050a9602cc62b03d13ecaa6d6f237a27a32ef0ffa35628545380ced01dd8b916c9042652d6f814993b8c56434826b5d8890879085057c642440b740930cdae94372ba7450472d4ef7dd2daaa6e389eac61385b93d002224202787270cf5c1818c343846447da7fca521a3e19a3e8e3651b625dfa23b10dde5083dddbd73cc92d56ceb6566c355ce9ef9df6523414621abf7174b23c0cd0a44f6510eca5ea3e7b77afe8704746c9608d4992e74332e42f54a65073565b50a8e152b81bac8047c5e638c795bf7de1e555739e764542e3dda4fc08358920f95a39e04564afd649f741d790d867179d6d5c9a7725ec7f75e25e450411cab3ac060d4ada5d4cdfe2aebafbbee2fc14cc1c69f58c27ba3c06f16dc08eaecbaed2cd53db724b2321f17da3035c1c95bec46961c4d6bbd50a85a24393ba4140223d37fb23240051a81958f72c3987061b872adc6469b01b5cc6e529d63baba09c66dadf46f654df97bd6f39010d95f754ea3f27cce5d7186ea42221102d152787b42be182c4909bcf3d840c2852ffe3b21312c8891c5c643e10052aafa2fa2f048df70412a85dd4cfe9bbbf1a9088f2f5cdf8475c57cb9993ce4c354b37d4d8795d44846e6bb1073cf0bf65ccfc33766d0dba0ab14c5c71b97312978c85fb825a0ff33f3fd0e1331e74492a2fbdcda29b98bca3413bb5a0d7fad13615d7f1c280e96701c14bb8b4645ef529661ee17c35e14478ef6cf78f6070db71aa8fc768dab18922cdeda809393c671df2b17cdf2de55157b9735369cf11b6047cd6ba0d9087357991063ffe8c05110289b42e0ec4230df0f7372dee302c1af489208cba04cc6323e8a4df2ff24bc5bdf687f0d5e2d3396c11a4cda03e248d70155d7079ac3d92d99a1f34eb883dfc9af45d94393749f3cba58923dffd946c3b5d9ef24d30e1ee19cd750370afc3c6bc3a7e310b518f5cc63e1461c2fdfdbee62cd5296432415f953f1b43b75d6a496bba6667fb1baf8f2a5bed77ac3115b64054bfd0927ed90e45b15f1c8142f86ff2d54b775ca40a75043ccf861272012cf680a7b701ca0fa32d6f66dd99d4d3ecdcadd67612670dfe2786764ef18dcf5954ce52642e50e3cfa92822a1d8609941ebedd96de1ecdd1cb24ccb37fefbcd6fed5a4c80b1c4901482b0ab6e8c808445cc4ed42251a565320b856f41fc49d72277e6c57bf87bdc14f8c7ee2a7b9f7f69e4628b34bca949afe08c411bfb2cdc4b51e3c84ce93afa4b70df58532460d7500a6df9004225578f61feca213ab78b75706a7fbd3f8e345b21899490f364fad11cfa4333231651c2e13a5936fac254dcd5ef9346c88ab6c735de799b1715d358bb7b99bf481238944e1e5b95f7e1d2a7afe5629c381572b3167ad5dd8f7b0eb1dcd7eb4d3ca5139fe0bb88ad984944b2ad9f8fd07671d4c770da6904a0a6142d4a688a9d6c04744fea8972d9c6cc0b956609a624624a753e2733185547d45547aae3b541e23a6e12d9acab9572049971ef258ebdc3c1a201230e16d7e5996dc1a221cee7d584dde9734beb1253e10f4977d8dbf006505927d4b8128f94f46a19a607659ba52e3d04f4f261e96c22fe94ea1c8afdd383122b3510c75e89326b7d8b88b8c738acec3d604cbba4c1b643e4b6ac8a1673b650af5abbb6729383caab36d0aca41a1c016b3a01d1bca6c1f7437d63e90b4595bff8c8da686c2f11fc11d0f25a97037fb7688fc3d1b4f6ad64ffbf1fcf2807586a9e6b7b637c1d63a1d2fa9237fa910940d416f468ab342ffb68fda38a76fd912dac70dcfea2f65ebacfd07a0d372444db0fd1abeef8c0249ec70b15473402c1e31b2445574342d6c77d224c48ad67be3f1d2631caccac1ddc08e4422b1cc24858831ec002117b404746696f40e8eb9a015d65cc855f65b8e0916807d5373c1fe9f95b8064854e11fd7a2b77cb3f8227992511f2c81352c01aaf1ca217c575426a6d2937df3e6b9121d8c6f525c45b25b093d30d7c9744c4fb2ac47d5f43392cbe93fe2c3a89ed643360adaff69489e28e756f34d6d0d7428477ec1dff98ec103c2da263d59a10d34af5590f82f1f35075f9a4323a26e78840a56203cfc033355b2485610afdc6c2ca090db3fb5fa8718c30eaf1e953864f8eb19fa25bb4eb2d935aa89d5752a1231c7096f6b2ecda99d363547aab5c86f8c1222dbefdc62ee895d242b85bbdd085b336231eca4f7b18c5adb2e4d0a19f8c95812a0686cc28c62ffa726232c63b39d58a9c542517ac7d74c641895ccb4a0e4413505c3c55d0c3beedabfbca974f2a8d6b65ec7cfe7433830796bf8760599601f20d3596118012f84cd3d3b99a2c0c70c8ebb4835ae65f05863cf1ccca72ae9481e99622b8a8fd62097ee36f96ed2a333402e3e51928c7580190150e03733d9c95e4c6efcf2873edd81813523218b51f6edc938fa4e44fcb4d9488a6944727869ed77930264fef90de9ee0693a40d1748b00cf96fe015a54bc26b64794f1cda0057c89ab1736ae8c4a60b5e1976077a198eb573780eee6ec8826a5fc8ee17924ee49b7239f3059d2f47be4ff799b0a3eeecb4c3469b9f903d22c805c3abcf064baa3629f67611fdf0f28220e8e59a9d3f930e6c4595ce9a6b63273b386ef16e532a0f3a5438c4313b340e3e9c118bb507542fd7a955de48d4f5ccb59e40f4d0fc97e4ac25fcc68ae4e633530b1ace408ef23fcc5d9798437a092ef3e143e191ab5b3194d2ad75001729b5203ca66df4baf4b9b5f6d6ff35abbf6d7c57dbd4c2c7e650fb11458f607df2cb05a39f5183fb3795c95e8e8cb416f2ee558ab0867738e91157f15b81e2ddb5fe6e8ffb870d933dcef9f95b43b4941295101c5a8eae9d4260a9d239c0d800656fb53d481590b59ae88af7fd06568c8e190f40675f6bb2c33334e289b13789572db3e95a9d65254661f4c337587e2f87efd11e2d86b8ef6c0cb37455573fe7cf0a5739a2d4ddab8a07165a11d7ad6291111c6650b7a7a0a07bf6c18a524f4705bf3e52fd599e9247a58b112f8a98fffcd8c9df986cd18a6daf4ca22b6b8902818a3fe3edcf9e7870b4bc960ea0df2403eef53982a6a681ad54d0233c0975133ae9fa542ccdf15ad3f08803cf86ad234b94f6ef482f8686a24929e627bb2517f70f4c8cb5f9b4b04afc5545f254507f22d7b6b307e43e0b562fdeb7700fb6496e97e7ad4487b3b737bfe6c911ff5ea2d18147a9d0a31acef9863360fc806e90d2df97d4daf0d8c142f6a173f4c4e05a3e54490a1853aca68efae2d383715fc712795ba91d72171d617979cdb5d913e57fe55a813a2f004a59a49ed8a3f9c7db5ca8f52f2790b2c2075a6df98a58c5586fe51466e9727cef2d03e43bd02049a836ee3d58061b22c26b17d018d57f5683167e0a40668e77e44a2eee725f7c2756aae5c9e92f55bbc4baa7200b1060c1372fafdd8992d9916fdfcb826b24247dcdcf77921031ff56444dcc383d19670274853132f65fc16c1d704508387bbcc23aaff80b5a930158b5d8b10be5a4a1123ae5f5819cd5b6bc34fffa1971fd2a98c7597a6a9b915b075a7c2828ed9f56cd53701a31416ad51413eb005905174b4761329fc7d2318cb1b88ac7708e172250cbe1c9b9ca72886d3a7b882038309020a7062550420d4c256fece812f1bb5b183d8f07514f251be8231a457319118417c65560a372b758f7a2ac5fdc807846f54658825edf44873f0b2a506908e6426031850dcc4c5a73697e4e916073cbd1c9c0ff0ffdb4177530543902cde08753d9a0b0b2ab2882e7d5a5db8b9df054c025fa65035f8c3b2cabdf2facc89e012a32691aa282f925e6e9c828568a2fe8ad303210260c2d56a0ccf3056a8180c7dc17bcc913943101c51d3065e9fce38899b62c3b2b2717244cdbbedc168ffde6bc3b371e70727bd883d982f8b9374b18c6a095480a96a3601301fafe9715844c27a8f613a13fcdec9881e78c2ef97c8c7b12a50db22d2d6d83cce080ab227861f0622e488c211552fee0bb5a94f16a8e1f68212fee07a78a66c0353f74be07cd200c9bbc9041e5649c5a0412f047d7e5a0f045f4edcdf9b6f52f6f05b226a1605f2d32fdd38eeb940559d96068d98ff2d6bd3f2460ec29718ccbe1c0bd27da47548cc201bee13f16acb5b928499a6ded5d65933e84f9e53b43c623e183b9e627d3e287287df2bb6901d8ccb817051780052595c32c9df1d1261a138e5abec62467e680721edf055d301ee7bdcd4f16ca29f23895f2e0e6adae553dc01ae6a428cfc30f9d584e8ce9030b3bb6c6669c54c86ea6b495728a0d51df2617636100b832d883156069b97c6469b1a648e8411602a02c229acb6c7e0ec970b355b872aedce373207fce57f84617a0f182b9e2b4abdacee649f695f3abcc773b5adcadc153f782bce5e58f2d38cecebb9aeedff31ce1c2ab05090687380e86515d9591768a922d9afdf207d660d9ecea60f543203900eabe819581539283ceaeda65f4965c4356cb93966c54fce4c98ff4c248d2793bc98934e9f73105a51db6f6053adc5e65a74980394c4f81283d71b4d4dd2b2c547279ff1639439cbaf4f511ebee021820525f89abace9f1888cc4c7d6ef262f6f88a3b6c3f000000000000000000000000000000000000000000000000000040a10171a242a32", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 36, - "comment": "signature that takes 14 iteration(s)", - "msg": "7300000000000000000000000000000000000000000000000000000000000000", - "sig": "55a13083e7de0c81f0d8fd40001a4a4f2cb59607d913efb4f4f81311c06c00fbecf2bc04f77d567067db4a14fd461038a48991d180ee1826c0c30692c47c42a2a1097dfec04acd5c7a7108981dacf78ae70cedda01334a10d89ebc8c7c1c8dcbdfe8c0f7e144cf830b0006f3be4bf0f748dcf242b0cd91a4cabcccb900ff06213959acc6537d19f16849587207f0407c0f963662d7525bab007e9e241cd09d2480db4f6a776eef833c578351eaf339da96333dd8b59fee06ccdb1cdb4d2004df3a953c9f403a6c3c716384babd35dc7ecaf0b678fb7ea75729b418427da89af299c342b07a779297a944740d591275cbcdb0a2080bf17bd3209d5894f8ba366be7eed1bbad5c45dcd05da865d02e66f57b2a876565636fcd0fab15f8da683b03b7cf6c0a2479e19d232aa76820519ee1b73613a7cc640b23e792d3322ae85b0f007c864cea4db20f4793e4b1e34cd8efd4a4f07c2efda24ded86ce7b33901b25e16232f27c0e11367221c947df2689828b6f13617f31baa6ac8103bb17ba575f67bacb129ba83992254663dc77420ffe4087f2f4277de4afafc00a0c197c72d44f0d92b606276bac42a8d46509f3a43891ec42ca8067dd3cfb9f2b891ce7d3636ee3ce27cd3f926563c9f103a7bda78f078186e3ed203f40108286bf71f6cb00b9478b06fda800511ce8d148c724cdbc8094e27ab9ba4b6049e906374db17ea7aa80eedfefbc41c0a9d53ec586b3510ec727b60991bafb721f7f281a94423c28c989267bc87ee5410afba73e2b5b54fa28258f2f9cacd38fbe4f7e3aebb09651bb99a3341ed94f211867bbd53b8f8220327c17d18d50f44afe81006ca87073220964ce522dc52bd6fe0cf49958f4b1a3b910e26dbcdc8cfc051116b13253e2e38c8f09c8a386d4dd6dcd4e972eed6e00630370424fa79894cb0f1a86befb90e01f5c4d5bb9d446e80e9e848e250287483205cdb67c6a3ce5502c6a5130e98f7682a0d61383d8cb35f74bda78a3f80ab29abd9a617a21f9d3b8c688cfa843149ef11c69e65f7af4e210ae223e664b6d19006f9cd16a46d2d5da6b4321aea86ec48645b7a16fca5f6af20b75d680ce726211cd86cb76984409be9c1b894e6639c8ffba320dbcaf180709905a37ededdd8d5d1ffd36886efc33d7a95602e5c38389fe3008bad8bc585f72659fa8cfc16c22a06bf8b20aca8f474cb1aa424cd50ec44fc04ac42a638060c22217435cd5507da97033c560259f208357317fce7cdf7a78ff2405559edae725532757f0e8bb00f51f9407c1edc61befb74522121a3b4dd236445cbd90cfb0a87a130269f19cb7a171eebe646647c56fbba0939b0f8da48d83382260cdbc2a9e17d2c7a3aa862a606251f06231c09c94219fc6c80a0910c7e40b46a1345c0d4e22cb990e3af93328869f50f47486688d601193f585d90d6da551005216c5aade79c3a9dd58714987d81ab8cf26e950893fe4d0c46dd267dd75dd04fe51835323301efdf1e831d07d4c354273c96e4b6c370aeae20660190f71cdc495f5bd7c8a8a7aaf183b45dadb42ca4b5669f5872e53aa9787243d955da6dece84cf3143b2d53b814232495452fd2facda3f47c89d702d8d0ed342e00041ce883477c1e8236af3abf2559b49cbaf69269b0b2863013d7d52290f0f114d82be9da2e1b4346b720e519f6c02cb4396f1c9679794a8efa6974f87c5661583c844df7e8dcfc852e314ea45f4ebe2dccf5dd2e54f80c68ef3254d790458db5ba234e51031a127bf78106b234600a690d6239c34fbc71f27ff59ebaeaab0ef436c3e4eb4502fb3ee1bae290d9194119b9f8657115909308f35efedfcdfc35d270798c6d461f45f8d13258733be9dfe975fb222a46ab42b8c50499aa06eb617b9a5a97c57a1c917aa61d546c47be9e34423e3943029ec4c8fb1804bf53a197360b984b1e8f7091d2e9f22786d8a2baf9ca5b86037980852f838b430df016238278bb6bebb66784e6f4dd29a1526c30cde485d15dbceb89100730823f048be32c5e7b64425140ce59ee991afd313878b2dd85de0fa6aa754760e12043318f6f1a24a5dea8753256283b20d4bfca840c7981b2693ee9ee86dc62d94ff20d715cd8671a99ed529cb5a6c651695337f25f0432b6bb6b3269bb25aa380d73e20be3eef260c775ed5a6615e6a9df312e6c2acc4f8132182fcd87350b88d9e984aaf82d8d63664e9e002297ecd7e409bedb7022b8f4516642878df0e2f641658de8b81c21d854ef199fca0ce6b6d00f3391e45283ce6e8c11c74a9937169a74eb5eeb051ca648d1c55655457f05766edc367a5599080399f89017db2514336e213749402484859d96c3cb8d263c23d398bf1e0300f0d3f618ee1d6549fcb20f583670057af966c5ed557a4e467024e5a27fdbe4e8a16f5ab123ffef097d959b1d07e7a19044a3119a8136c43f34b87d696a855ceb7724fa243b03341633d70ac3908ec2a5fe786ead035e38a20904cfe9224fdfa1ba0cc8d1820be09e4b6b9906ca97bec05f9406b1a707e0fe273fb15887cba215cb87af06715a4f1dba7545d965002ad1f6bece1815d7001bff98609b840f4e813f71c80d2e6d9b25bdd665b2fb6213bbd43d81a58e2dc6ab71ad4b89a79463133aa5a2c4af5b3aa9e47df9a2f396e356a89272661f92f11133ac1c2e103d6a949f494bd506307059f1ef440ba5df4025778d8ea9e887fbc4c564ad860c49f6efeb960a167d1d4cc7fa34404d1e39c273e7aafd54adbad6f805427a8c33c8849ca8564d2a7298975289067fe5af22a09ee22f77dc361852ee31c5c55f584ab1601f0e0b384fe8e1d072f283ee5a20c6e2d0f07096aee3133c390c920daaaa33b73723533f2aa205a2a53b67b7043c0b0b0073918a9afee74626781a9bc3566367b37ccb516d1402bc0d074f78c48b14b9b0e0cb62ffe2106225b8c3ea2b78ab0a1e768ae4761cb9ce13d3b484ba2544f4e5728c1e001eb969c0b407ab25d901d5415206d1aee1c5588352192cbb2bc806c521ab1687d2d44f63b4277f72237146c74b5a018fcbababf6c9b0d5cc37a448ad9172c0262be0e3e032b086954e5ef01225b0599b911bb10bd6f569593c29820b70f39c3850aaac84942173b04c51ec0c30e75b3d4abe3cbcca5b1f2151fa306109fb1216577891b32abab6c45db20c4b794779234eff9c613c4b64bc8e1b2b4f4c9edf0627c409ba51f2784dd081a4a0b6cab5788d0044d3906cbcb4316be43734402d4585dcfb8a3e2e8dff902edad2574796c5826219728220b8f7c7225c4f17f08d2286488f12156b07df5600b3cb42347f2eeb2284342d2f672da1736751990db651b79f04931a3fd64db5f7a7bad8c3d28b4f2548df12b19cecdbcae8f0aeb60459f1f5a7d4bd402161fb5cf4c126800763129a1dfeb96471cb822e30d3b145162b3ebca10946fc1adc28ce6d5c9255288f601e50ad34668bd018eb28f84763f57810071415be8e188d5dba713946730392f6d9cc7f8459feb21742a63a6994175990d9b090b052d3f8b207eae4e2130f182e30e8ddb6f3606199b9619188bbb229fa8310de013a332f095c4e8803c87a8c4d114544923b6dff6de5d8d5413feeac8c8c18e5f5adc61137d2848d4d0291c5b47d8a7eed0243757bf618edf10292ddf9f7e2839d188b0c57d3579638753c2587fb506b5911c81599862066a2a06592ededb3d6eae6cfd9ac52fa62d769b4e32258bef5aae0feb060b3bf40dcf286c8cc29925b4093675430233ef89506aae8afff956a60c0cc61189a28aed789d14f0c2297664a7075153ac367245337ae86112b5eafadfa38c879dbd0da8cf62cb72854082567c6eb4f8b47bf7834cefbc6a47e3b78ecf69a452fa9577f3295effbfdbdd7e6864fcb2fa20875eb5c15a67eb7850a443ff0331a798dc49148bf988eb3d977a228b574e34f865a1cb0d13f89c7b17dabf6cc5dc396fcaa9ee473cdf03ffea94154c05f577295769d34ab4c8ec7c2892b70fe680d35f509bbad5e3d77cca2b64e16535a36124388025c821fe62d02fa8b6bffe286c1ee3e9bc792a5f2973094dcba0154717e648e411f7645be474bb986d100c924bb7d27b0a8a95fb4418b9f67c5d3b8da199210405fef480e37f17713be2bdcc804c9a257b931cdf8aa69b344bae2603b7a0f0ef25eaa899e2fd3f471f5cdf9e3b17bfce15c318004ab75754fb5a4cd7a4fb2d6b6543bd4513255a5ac6979aae51c5cbe2e9e272cfe27c5535f8725be5c47b474a0ff7c2b7373f3c429750e81438b72ac5ae81369d9cb453e3fd04cfbe5837b0b5bac23ebc2e61789f371be52cc082fd4d991428883c4e8fec0397aac8c9240695f6a0588118eb55fe4aa5ff7a12a08bce3872cc54979226ae3bee66a551db930aa86fdc4e50d33a7d8fa68124fe90d97be38197517fa1b1aafc984814b5d9676bd1a3296a2cac6d61d9ecf5f97fabc513e81f6073d752af7a2c067473849a1262392f4d448d9677fb6afd09a031b6f3da07ffc107f7410301774d90f42bdfbde71d858d57026d8570f8000ba1df13dcd9d9149d4b746f47a86fb7dd94f7686c5987c549c1b5cb51e324f8756818c49e65acafad7b680c8fb8b812f94ffa66c2fedb5660dbaf647a9075d2d754a02c7af18ba4b2777194f0deaeeaf0485a016c0b0c3b542790d2acddea465102dbeb137ca5a08346832e15f6dec70d7902dd55dd1af0b6d20ddade7b1d8ca6474ab3f84c2e6a2e06d3e38c7217184a895ee494befeeeb9ebb4ca4524237375d069e4b0bdfba9b94018e3dee51510b1a82fa5930dbe2a39b6b2e395beded5a453225a747f4e5a30997125687c12b5793ce26bde5b262db06982b18d03fe628c6d7e0485d7c01428aed8e9783594fdf7a2538c85ed8c685dd3c214165b33fb2a7fe69d6907152cd9fa1f768cec3f5f2c03a6845cd94b123565499824fa57ea89bc6fdab4be1a24e4e4561ffc0b73a9c66d20962f8705906a309b2da5ba51c6cda7caff1b292eca6ed594016f10d9baf86f3f8d7204bd618c27e4889aabfb06cb794c05368b9eb77062f9c1febde2120a76edcf56471984a51c3a7460c12dc84dc04fd506c0cc901deb77ee85166b56958d5b54b98d9c4de5e821037d193fc797a9b81a668afd1013c5179b6317a475ce301b23cfc2a5ecac8362d9e8beed978afab8736903f5dccaf8cbc98a9cd5090267222969eb91cad13fb0adcb9a864df4e278916a4e0dd52be05efb5a7a3a60ed1ad6fc1fa9d87208d3cfd83ae4de21571fbc9e0db58eb9f6667cb25959aaa397e5e7ade5a45641bd04258572917c5422e9ae6b0a52b34dda1c4b08af7dc08373c8d567960a7bf4f45e7509668db95e167326ff905e6c73be44899bfd179fcfb917ae8e20d9c715d792cc01a4f21563708c9385c9b574f2153b861c14603090954dd572ec9715566c6877727a4d20e103c3b680798c474ae0d2040732ea4dd7f6c903f381d06071a5c3c21516960e4136a55632f1bf86a75189937b6f5e3508b9577df87d4cccd5b3861d466b842eab8035531ea5fc850a26959dc71c1c5188ecc1d4d89827e473ec92dad886171aaffc72e726eee823f65500de25d766aafdb9977d9b3c7f6be729faf99e9335e36aaf81271acaf1c5bfba8fa8f1644f46a343aa015258997ca5891d6140742bf330f367f16acad62d39d42e2263456f181c876575d7a43049c167af822d66d589977136eeb215ffea72e6363b6ad651a6f13d3d8da0e6a9cbf5375d97f930eea22f89ed17f4af554757f329d203fe51b71b7729db9b6074f71c1311fd1b21824c59c5c413445212c28a34964b5e48599ba4e6a4710004afe6086405ff3ea23fb81e77727fda81696852c8feff150b1128b29b92ae64dbbba7d09a8b7ae8c381b7383b3ef5b1cb8ece64679fb703fd5c46318a08bbc259017efff82273e7d75f27abd6cc5a8ee7a85f5e7d4daa3c45c89b58ab339a04677ecf1dacdc36fa9da3b49b4170cbd39c85d062011424f510bebc1b89703d1f75d29d80e964812aacdc1da3242f154ea25f862c67d2ef9c9c4d38974beda84ae0cdb9e09f188a65a795b6aa4c55b4ddc5cf37b6b9aff234d12f229edb7017c71f6e4df6f0fafbf960506fb17edd7845bab02484d5dec474db355f8b21225d435f88ad507c795c545cc2633761fd538eaafd76431dd72973f0ec1c8cea2a7f0c752ad0f4e5018490d79f1d7fa754f1ef6d95c47fe9e28521e5b5f4c66081ec5c0992d540083ef0d4986de0091fde0a0873a0630f6b2644fca87ca07f0c10e1d463ff2b68e2fcd29d96f6d85b3e43e068ea99755edb52f0d817cfceb040c5e7bd93d64b07e8d09906da4f867744aae6e6634c8f52a86952b045e9100aba4529a26365dd75f9f39c8c201753cf821acf6f106ec1c200183574bbbedc05165a88cae1f4fa00050d3594ab41bd0656b3b825545c92b6c3ccfc000000000000000000000000000000000000000000000000000000000000000000000000040b1316191b1f27", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 37, - "comment": "signature that takes 15 iteration(s)", - "msg": "2a00000000000000000000000000000000000000000000000000000000000000", - "sig": "123f4f6cb3cc0f73536cd4cf412958953807d551ec6c70ea9544dd410b837d37788ae672a00bd3fa1a3a540c7d6802e25955179a5b00e67b06defbeb29447ca1c0040c70670bda78bc68e75527aa569f7f87c9d5705216458184531a802e182d77ec0a07a2be7ae61ce7cae9b470388cbebe1d0b5083bd46f0c11f9d5dcd87cebf1e544e53816537916ab9b1996db164050200f08041a9be0102881173e6006015e716600b36dd11423f018196e7c34793e6b1112785b3162be366fa98d14c6f2b9f66c927c23cd49d1ab22b10d8ab0c6d9ac627fe7d6941395f96dbe1a26712e8cbc54e332b613631eba1625c5140224bba9fca7c94aeb2d76f76e465d340ce8cedaed60719b3252a5aa27742315895006c95df12894803d20c36bb61bdefa2d641f7ce717a55bc699755c0fd56ef9fdbde98ad0eddc763ad4c7d5cfe2481b662a985cfea7761dd72db3db8b2942c7134d7216465d678f97a7333769872d2ac3902df2a7acc71de42fc1913791e0d73f041bf33e2baadc4c564f65a9c50a372439f3e405ed341befd092ebd3a722c2affa0f69c1e72c2bc7acf5d285cb210e4e5492296f1d014e11910f63295cadfc4ebafba3cf66ce0419114c248c37e453fc293eee941fe8e2d68223e64741dd51389d75a2b90e9e23de9b4a72348c55581a6462a6c584dc47a026e0544955326efe2a502964fdd2109ac6fcbee45fa033743ea53c4ec16fabf1fc120af3e2b1f88df952242bc80ad579beb4c58dbf13fde0aeefd048796ec571207aaa81424a6825848270004e446206dded61d7e23e6ca7202f43981fd5da67c12ff0a61db2d01134fd52aac84588c9ebbb690c816220ccfc3fd3452e14e9150fe81bd1dd1047f41dc3c8d5d3fd5b241daac87bc6b350a09d5c6962dbc198b5639300af93237f333d60ab120f3637314abe295cf37a1c133cbe60d1d67c8b5eb71fd7f8a76b587deb7aab3b8db09c10328af080eceea4671cbb8f88772e9e01cb92b85fd09846bfdacb5616f4650e3c23612d2adf8c2c6fe345034c981e8f6a1e85ce71ec3731fdf209393a9eca6adb0c49157d2058de1e148e9d2f279123ed741543afbab9b8d1408d38be81187b10cd6e0606fd30b43fede67be8575202497fe79060c1cc0147ac32c6b24ea4e037ad6246eb6e85b53707e2bc1d80d7a57fbecb925d4336ba0460d082914fa420a136338197715c8d172e663d4977672a63058870647341d225ae705f616534d616a964118b8a1bc247fd35282663a7aca93113f7f31e43dd59532a8003e40b9ae0d4b6f65f35fde37fd32c6b98e5d5b9930aa3f09d8c0d389d8411d7a6738459d6e97c094df417da3b96b45cb06e527c8af9ec05c2073a714a7d5bbf881c8780379136ca91208a2247f78d720acdbb8dd6c783bbb8fb5ff0d5b81f6a490f7cf603c693c99ab9a04d2f49e7f4da5c50bf2903e8b5523854d1b2d9c34a9769b5be86c6b4658345795ea58091110d35e0513c73baaff657337de3cd572bbfab5059d962a12dedbf395f25e724c04c016e7de555e5dd45251ddad2e7c099b01dbd5a5c2df2918080474849a3e6f1ce796658070baa123672e7def9706569772a802c7e2e20d8d125bf5adf6f075238b757849fe5b41a23fc92a159b19d2f04a3f708b99830ed0fe0c99bb6580e5db829485f05d5bd790f177b25fcbb75c1cb37f384cb75660dd52d1f1a696509ebf9f3fbdceb7d20d2cd6f2c9998a9e4fb471b255467664a4deeb052d8e515200d4432057ca0a06106f74f3d27d68eda5f5567861b1d7df4decddeeed2a45f1e99566a72c246933662cdd27348600483a9fd45d5f761025962b31da46fdd46fa07e57f1401a1a2b8e52b704153796e6ef85419df01b44fc92057ea0e295d35d00e7ae3642a1c74066a9abe0889ec4638fb011e2c6e48fe681afb75c5ca0b939fd5844c7e06d830a940f7bd0d8a9d361f1a6103d7d1474064cd212025e0c3ad26fcb5e97b48e51d3df95bdc07c364b25a449f32a0099385561b0b90101d5bc81c9e86bc2af5c4cdaeb5a21266fe80a68e70de0ce127896ffb83e7ab6379f09451cef345a1a14a5e153a528a91683f485f9a8fbd9cb5aea9724bc1c73fea5144d4c3103cad378c77d3236fc5d4c5fb27c39185c1f36cc3dec16ed69df3e4e01b0117f07719c8fb9fe9a3764a1930863f80e0a274703cd3e8e5b45c05c73f254bdc2b235944c67895d01704c94fc27869cd138646c608b560ca0aa7311c21f1dfae744f533163c42cff64cbead971e03af0bada772debe019313c40bf6b4bc351c446cf170fc3e6b9e71ef4f19d61e6b833402111c042deab6a351f13d5e03fa3137b24769cf4bea7cdcb0f0f705ae413ff3df82365952f7a6472425611ddd60f2f84a3a549c8667ddb615bbe48d8588660f9efd7e630aeffcd70fa43a3c2e12043151ef1ef198f6759bd1fae3258b9c1ff1d80fd94250b625936598dc8c06693c12112d20254c3374054520dae6bd5d1eca0635cc4bc8c9719a2e85201830cdd42903848ea99c7e07b1d5976f97c64bef0dd3fe23f74c2af42b982a076f2614a6e7df0d0eb964b292182c33f1b6ccc662318fcfaa664e9c1ef0b39e4a7ac2207869826a2d338bf188eca40d5c0da8fa36db3b89ba7b940079d5df1b56befd678ca29f0b6f7f1e9e8026e0fdfe7724304d31368600601c22342a5c5e5b5d0c1eb8f8d149cc46bc2bc706a844537ce272b3259580c674ff45bd820654f442097efa812265d56907407f58e127e8c44792a5c416586689585e37052257d0f633d6b20581f6ed1945cad42d25f8826d587f8eb7f05de7f1ab3fbb0bec947a9b24af9505d4d7c6300d200d447e3cb7186405e162d58b733eae467ca34d9916230777bf2ac4b91988b66b9d24902c8c32d866c4e842c1b3f78e57b43250cddcb9a3e532bdea293fb224e92e071927b7da1d2d8bae2c13e3b4309190ec10c5b534d74bd9ab876558b8752e3a18e8d724510054fde72a5651cc4cc2b7dbbff8b3ab2857312302eab679c16acb2c57971d99b56f3b76320fa5cbcf108dc1e6bf5d46696a82b9c9f375c906147fb03a70538994442939e7f26bbe517b7a6abcc21fd0f1fc15eb4679acc36039b9148702ba4a91de6083ad7c2cf76335240360157a3e9a5e02c0cc56bd5974af9ecc8350aca6b5372b95d184345d079053bc7c80cf0c8e13a93ab6d16fa44d55bc6d31590493371e20b370a660cad9e9c47a2af8e2feebd633ae00ec810d4eabc8652a52d1384bccc08097668e96e51f1329c631beef13ca3f305202ef81d4b391cf8ec3461f1017594a078d54565d7783409800adaacfb7619b1c9538f22f38267c38de2687b0262ea1e644a462c6bbc5d63c8953c6515e8630dd3f11be7a00eed83245ec44b69b9255e8c0735011cc33964e41e25da5ae08fa1176bc8c1d7057e621551226bb2cfff9251683979eb79edef919e1d2458261674c8aa2c03dc7d5f7c05d6c0b2f724bd852cc67d7ee11ae4c3d57a917b773fa6f6a4665367858c68a8d8901b8cb5343367ffa204c403499f2411ec2bd80efefd5ed4da7beba9aadeddc4174e4e021b0638e8688f483d109f839f790f6a896c757d6173d5b7477a259e9ed4e89b547566c66ee5c93c7c2250c2ebefb40906b9dcee9bdc276a4b357b4361eb956eb212203e2d245f150e235e9a50f751377038ea9960a500b466caa12bf4fb872301d79c60bfa8d11df1007bb2e856f1b23e4ee064bfb00cb5c766912b0966996c506e5e994882d0e4ba406f5a8b6be2e7c13bb77e71b273498bf29a1c23f05e8eaafa77a57ffaa1c8080697482af0dadc27735a48608b087b8ffba2c6c77d76d69b7c89ef0928d68a08556b923295fda0ef1e88c05259068964fe164d840b684af1139561e36ac500506f270a78a161d4ebc116c01217f184196044916a4f4135c66f09cf508c2af5a9acc4e206d6302d447acbdf7d03bbc567645d71a0a4059fdb5358861f9b4475bc3469e7da726958b6a3773d0f30b22ab620298b4546b1954d2e1699e73d3bfa6fb236e9220b48eee09676d8c33bd463d0098b026db4939c2973bbf041e08d3e2aceb171f081dcd62816bce549f18f6a8b47293287d3f0257df39d86f4ab4f962c38a692771ae5ea82513472f342e892f67e998cce2ac2989f364947c9b5408353ec53734ba491a75dbfa377d8805e7c7ad62ea5a64e528029b41f1aae7aae21ae27c2c1ffdd8ed17499a8b96aa35a72dc6d01b96d289602e6e82be52d12ab5279798c08dc560df568f3a5d0ced771018cb29a95fe887a5d591c330a86b3c1a854e2714f106a616d856120b068bed1fa7e625b13bc3d4805343502ceb6c5c12828e9799e8ddb11abcb6cb1239b4029d1658cccbea93a43523433156b87d7ee524616c21c636524c35840c2d58c23a4a5e6c2b7f11de10566951b91e25f7ebe1e8b1d98f77fc3ea01475adf6469b33897c7979cf11451c676496e915b82ec5f971ce557c585270c71709782041a38828159dae53f20633f152e1ca6f976c1427df6811011bd84511c0f4cf7d4ce800c70d4c4c00ba2c077ded6a7802172d23872e3cee1490f944f1f87a69c32e9b432836af88bbfdfd617d703b329149a48558d47b991d9b9964e0689a7bb1694fe4299be1b0e468182212a07f388e9b9fd2b07f886c903ca5d564788edbde3384cb69b61f5664a0e21bc11b44611a855b4f04e0e5ecfe3f917925905eff6aaff29cdd0389d2205c2fd7b19154ca96dac6a2d6db0d44e797230d939a4e79653de083e0bd29e302faf5abe47bbc86f8cab0847ce02732491bfa1f9a54bfc0ba7f5d7657fa98deeb68765fcc4819b50a24b6721d3ff0a591a008a61060343ff40aa27e3950016df1f24a2c4ab84d7d5051077dbf8e4a482e41d0a3880bb63d2f5a044d0c5d7efc88e59f657e71901d18e36d97ffee3d16256ea46fd2f2e74ac7251208659cede682b1d78a19c73601a3f3ba7b36ee47867a441e648a93c0e6a1a4ad2eda0c466ab0fbb7548951c04b491bbbdc3026537a323b05a922e2bd9b375e806c74766692929e65fa9ca8c1c0ca965c7eb421bf44f285141e87e55763303ec40ff4c12b19187bf5daf8ea2c678396232198b2c98b4588590f971ab2f3d7a10e8a0b930ac818029dbc3bf341bdd4550d0d0a0a13e59c2d05dc8c2ab746e8bddb8ca5bb3f2a4e0b1be1fc4f321dd72cadc2e49566f8f727e898b89b223d97bb3c14ffab4da467728adb508f276c3cabbd9811b3b44175eec50f4044d8648cdae05b0634fcf7a420ce59055f108b7daec05f0bc685b8edc513bbed512fa1102e1595f0964cfc81faa4cdb12640e71e2c830be5dbd96472aa306b916bc931febc2c6f14f343d780394465d7f2a538fc8ef5e653410a496ca4e24a5192b8349cfffeca1713db147e47ffdea7f4f06e1981e3b28d2d1be4868f4347cfed55fd4ae44edca8a62a06f857ede40441991489cc5505a49475953df8265e51cb1efa94f5ddddf863a29b7464b8a070a4059381f6491ca724aa81434ec0bb9f80fce1c4876beeef18eb3d1065510ba3f828a170f928ca46a029f19c13e31880cb7201dd6a3c8553b28a8bc6cd0813a64139e6dea93d7437498ef733fbf907be4cb9d6e01d5c2a7650bdbb74b6dacd1f97ee3aa2090d3b2645a36cac2dc3a991a6e862984c16f72719867852bc96d5931bc92173453ce224742f48c180538b090f3a24356b608f21b8fca3aa2ee70370b4b425b03a20a0bd35f2c766a6bf979512c4867d06cc78aa3051c32f88dfcaf286efbb2abfeb0bec98f3b61878613c1a632e22e221a11cb886baf1c9496f994a09ed4744fe0eef3861fb3ee686072f28514cfdb4daeb97501d17dfe30888f1a21c6f806418b38172f5c916c42fa1f32507ffb5efe6d9fd7d9578dff9579c68d18feca3dd68bc612fea7837a7471ab748ef2ad7183c068cb47c0796e477c2483f873adeaa20e6653bd23f943b765f7ddb860ecb5d14f11525f1347941a76d74826e1a123976a6eb0d7cf47bfc5885954b413eaa8233fc994d042733f9075552eed59e8a6d17c6eaeaa18f022cf13000f2904aa7f80411383f245799008b49edd15e6550352f2f3a74a99660a0b00884b57a06c0c4c607769c5b92c1976f516fa6a96e3cc6ec49763a2e682c99bf30157e6f2b0f553eb4dd6c01f5b1c801ce24d0fe39498608031b7d56b48c2d70e387d88e93388cf601f29126c7d96fc191365f968db7628955e1ab3c66333be6450bc8967ed2737a6999583799cbd98b88483c23bcdc4e5a365158456d799d4370576a6aa29987ee8fd9babafa4f69ba2a827c579f08a9977d17334e03cd3727cd74c4a5307f8f9d77a4b1f97db4f08bc55d3c64cdbdc13076e9fb739e426dc00647cfe9005e607ba2b4cfe20c7aade6061a5b8bbce002d3db0c212c364d5d738da816244456678385ccdcf1142352666bc8ebef040d28343e7be8edfd000000000000000000000000000000000000080c12151e283039", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 38, - "comment": "signature that takes 16 iteration(s)", - "msg": "1b00000000000000000000000000000000000000000000000000000000000000", - "sig": "faf6c364df39832144796c0a8b254f0e118780915bdf3db6937bc63318a0709b8f1af8480fa33a2605d9367fdbbc02501b404afbbe23a9b302b2cfd7762ab14d95942361b73045ca114826efaac3d52cd45ae2a95c67b8cec78d417f72d22fe545eec9cc844cff349ceb3c89c7c9c97d7763055c3c9b6f1614ad38a979604c408f98bb6d15a54e464cf970f896ee13acbd2341330f66888b0c818b78d3ba748648740857d3c6f279eef3bc612b0da8a33812f7be7b6da9c3803a43f718fc120586d3efcb9d3a16ce2453011f36f90adeb14f5656d32d7b5dcb1dfc47ebf946f01d8274e627854b4beb1056f9dfacdc1dcd8345d974f16711d819b405114d140a9bc6d71ad6ea05967ef7a4aaea707088579b351fbe76b94f0fbb146895b9c2a401c4b6e95983d563b8d213cd7935ae561a0ca7d8f98e30ca59e49e5ae145075073d505d7bfc0e8c8316da1ce4db35e8a28121ca41b347d27609a38b806939c6a7c539c86a8fa99bf9eec69856f62b980fd2b77b98dbe3a7b1866bb2c46dc577002ac47aa303b29136294435549cc8691f054b6d3aac80ede2cfbf7adc193436ffa02ea0cfaf2fc82b32633055460692b76b3df53b71f8ea5a8191ee6144adf79605c7fdfd7ae4632ebb8677db8c3c83a2306692e57c1488f54580e636de4ec2a414390b7feff3c9e0869051f3b68f62c247121c9e7af05b400b08935facff38f824196363890751557389e3c3299dc954646c73598c5f667443e537dce0d853ca8e95c1fc4a0b94827d12b8e3daaec3466ba668d7e0a755cf9b990f86e45577a4c3db62a4c57b0dd9f43c44d474b483064fe490c488c777b5f9c7e129686ba1d9cf9494f04d3ea31f8da5548e2ec1a66d67f7b6137c95d9470bc8910487a5db370b84521c2e3b36d218b2a9e7552d594da94b6564de16dc3eba3750d00ac0aeaa1fdb076d4c4f86eeace6a7ade8a4c03973ba7c0dc4523a765a55ee980ca652098b236b52db830a91b3a83d0835895c46eca48aafa919e7309aab5993793c2de6ca0c89e739f29b833fc655607e545097740dae1b0ffbdb063f3ea57d9e9ca6654181b2d18d6cb128979df81ed592a5ae090eeeb305036f684e5e9e2385320ec554bffa257627d161e87fd2f94c149b8addba426669adb783f256c3a774b8c397c4c8aa27f6a3b3a9ae2615ffdb485adec21929c49ddf827a10f6cee3b623ca026cd12bf75a94d7777f79b71029378e6c366a1cf5be772997d33f253b0436d32b6addd6795417b7db5e226ac5baf47fecbc5ed3ab0368089a3b239bb96d5677c03ae2dbc12dcc22c991f7be0851a2dcb553ab014399708c0bdd0a6efdd49e5178212477f6283f5d07dfc178a7fd6fade6ab5f3a388736a5af1de20173055da23ddc74c77b11774aa2472aa0d1f8edae5db1a43caf20b7518b667d5a294a1460d0047dcd8e45d4dc6af3c12f912541471ce1419cbaa12dc35e32b151d90ad9b1a70d96a530aeda4add317ca1b45202cdbec7b6f7138ad9405c36c2bf920639bce136303d3ddaaac49627f8455cc575614bc82a643b2789308b4e0c2140f1c226657500d996e57f15196b7b7aee6c6768c3206c20656a5b03f9e5974e61186fcde401d71ec788765687f73b8f3cec07218fb4db54ab60eea5bbaf2ee9884ebb7526a983d9ea18daf1645d1438794cd4b8b8dd6425e08615b4fae5926eb248ce7877abfa072a2c6f15cf66569bfdfe880c3d9eb2ac51d0cc768b2c3ba7de3b15f1f57853ffe6619ff7d798ba1b48045ab4201ecd57cddd9952aaf0bd76805e5bf696fe49454adc0cb60627492fad27f56e8f96c266b95a2a31a7a7890c5cd97da941ffce30c3a093ee38969a56134681fb8793b9de118c3cb278b4f43602d548c34bdf0a9c3cf7f5c6ecb70515df102817f5b6343d7088480f9fc99de8cc99c693165646eec54d6edcaf7ecde6ec2373adfb035fc09d146767fc635934ef59d41f65683919d59ab6b68ba1e120c9eec9eeed774b5dd31e900e610fe19137add46f23eefd7df6ed3ca950fbb716d24453e0036e7b08fb37c6a97ffa213a2327700e9d2a8ff3f72f9a5d84f8d7b0736134f3d1bef4101aed7855eb8987ecb969b47349e5cc68d474b2c66dbbc6bfd454457e19895d4201edbc7907e2049f1dca54c4094793c601b11094eab0038c87ee10b1dc5421196ec09fe9136c2758b4c2f51448966f58cad228f2e2f98e920feff550d4d2d8ef76973ad40b679cff92d4d234f5bb5373baa880654b14c41902b746f7563e79169a8b9aaf0183f6acd2253a4837ed05bd89b15642e25b18f16c56be25decb5b2a0651eff4bc0da8da8c90e02c48b3675f48b5e46f31270ead9248efcc14d9f5dbcea916a36f7d88ceeae3415f209158bb3192fd1e43cebf06c555a65504d907c16cc9fa188ce5858fda7f768e1cec620933a8250f72dd73c10f7e62074d628c22f20699765b3eb4fe95170d16678875f2015bdaab6e29f4ed7fe60e7fe237f89965eccc34a0d7cbe0e8c291ac8ce20964000b1792a4a659cfa52b3f7edb8a09286686ac16d6e963d001c4ea0a782da54f1138c0aaffbfdfd390d52f36ae1cb609fb7012a20279c20c00aa15fda4dc5844b5d3b1d35e78009182510a26b957ede5a5b106c029b8a1f80443e4f68b5bb95b0d684c7ebffb0390b0df9ef817d827c6959f5c78163804703b2b762809bbdd7d3d3e2aeacccecb95a0b270c3b9b710fc3eebd517bc0e94dcac0154a3f4546f19b4aef7a0cedf3ef6e26529b426db7fc8733967d308ef9c76ddf7b80a2bcfec6ceb484759fb884cd3b619507c7652b700ccacf3ddfc97a5f15183aacc7107f7779407c135ca6cfe5bd6965cc80d1ab74df306d46d5344e0bc0aeca8cb1b2ac485342015c7e8e7aefc85dadac7690112a6f8e2d343ae3e276f3a11f138079a0c625bc1a95db81133d8488ff5f88e6eb9c72fbcfb22788cd6f59cb80722dca46308419f437d32a04443a8f2baa91936eb2d8b4185d137cb106988285d4548d2c31ebb030342cff237f3b7bb790c0fd8e82147bb169dd83a7c07dabb448f8ee2634a306dd5d11ffc1c4bd74957c3133dc02736c20bf2b30ec54db72d95aef97a454247d269ebbcb19f18a34d4a92ecf5c1109b96219f6f700d4ceaa485803618efeb921d36687e9539edc86dc2500069284b12e05b05ef2eb7c3c65a7a42830ec7e468f443817eb402f15a7d75af0daaf986358b3adaca0975a2c5f1546d49e2a1804eb2171b72af8e29a43e72ebaf221a4c6e1808e5547c2d953b9705fde1a0c9f23fa7eae63ec132870e6e8bce49cb6f7b4b57bbb9da945f30ae7e82a32ce6cfa54d3f33ba05dc9bc72add70b304ddccff823964c4626b6b5a9c1e0599ffe245f12237e708b066ae703fb576844d8d9896a7d49517217eb69c4c3ec81ae277a5e769739b8555d26933292f76b67ef928d837a87f1eae673fb45b8f49fe652f414c32fb6b7de55f26cf6b27a1d5f8f15ff98f77e81ee7e8d25733a2ae47fc536e3dc03e11aa01213060bbb540bb95e0088e976e38d791080ff3fd5a7c4284015106c7ca9fafde0f32d3d2e83238910e57f926e4db86963580b50572121b18e32ba1d83953b84db50b1858f31001d29062f5b11fc8ea339a691bb47baa7ba06f49170a63688bdd71006cd032eb16f6e471f46d0521cf760524b1863275403440721704682546594376322038b7f6e50b8258013a8622f60a9e3ee15c36b9a57bdc27fc86f93571ab627bbf09ba7bdba1efcb13ce4b34e902ff36f5f7c3ec030f1b811884ce7d07508927fa7e58e56b42ad7513280a7f9a5d565e40d96253d4fdfc5b14f8ced9c755b5a97bc32935b8954c453401323c61fa6a710cccf817fe991f239f9c664c0c8d0e74ea9fae22d545a86b30b47c2eb21839e3eadffcb46ee4d0f3afbba7c77d0822cc77f5f71635e73c417404dcb8daa810ad74d29f5afa8018076c407a85eaf9f87a1177a0b7bc25380348b4529883f49d89fbc2ec4d23faa10b3e15c4a69f9efd4c904ad9c7c890215f46ab328974596a593d908748e19e816f0f2029d35e11c673bfc049fbda6f2bea677b9af34003ca39557a38260551a5c5475a370ebc1fe0584bcdbc4855e9da0cc8c9ef6e9faf66f54be6df5725b3ec4482d2e2627018361dd5ed7e1ffa4061acb9d4de991b271237b03aed85386a9a67420d9705defc99a5f4a4f25bb800c7f803169d9e273ffc5afbd1a9b1ec81a4423fc335e1e89245db3a5e7a3793b00588624373cc4ed3159af5835e71026aa3e2bee99f0b64b32597f380e0071eb1ff5d0ba559b4398a0ae570f93f193fa68f6aef8c9296a6b6f1de9dfcc8c21ad79227af7ff219af68b947c77b6157fda3eac433800428c62e1fee68b697411cead39d84637f1151c0f41492525a6bdea65c1604974b3d0d4cfd9eb33784e54997368dde58a21df10ed4c6042572c302d3cbc9293a5b2e5cc3b723e0e06ebac2afa7f141cda971a8af161b0c03bbc15cc689182396e933ac0fa9a8d0f76bd639a43e19fcd2ae4bda7da83f6fc3fec43f61892a74a4ca7a51bc70a91a207b49f1b09dcb3844dfe48ede9bba7dcf623ac2c8ff6c45a524a1fb8ac91075425bdf3811441f9560bc1c46c97015c21858e221a9c7e50d3997352fb96a92b9ff1b4fd77673bc43c136486719df59addeaeba9b48f23afea6b91dbd5c1ebfec305fbb65daf782743adf1ccc61f821b72890c458c2c6a5a7daa7c4daad45434ce885614854703324aa955b5b00ea4a8ec00d183db926ef949bdb0b60b96eec9317d59079b7bc1e6fa189b88045e2b646eb5f98cb325bea130875192bdf489da24f051c7278805dd0ee579e29828d05a6eae83ac6a3724236dbf6713b9447f1d11dae57682b118a826e343de9f316b2898699e1a4128d9369f2579159589b141c267314b753bde4980426ff71c6c19f0e1dea7bd1bd5e60afba9648dd9c4890fa533f49a4fd099c8c94ae188d898216384fb2806d6176053473aa5aadfe5ed609569f2faecea70be9285ba2a0a0349e5f5e1952e4c3fc6792a14287f0b34187f1cff657de7e3930bda94b7e4391906ed9220b28e1e815782ae00ada4cf9ab2a5dbbcda53a734886645ef97ad826aac0df839698430943bb81880fda680a6b4ccf52b768190e1ab80e6f57132fa8094cd71bf492df28f612d51d785cc3c9c59f7fd90600a6a562c9d26b7a8c494b6dbdc526a32b6f411cd4e6eefafddd44d97a58a8a63b68be8e27f7faf90d8412e377c35b65e8511f1b67f9eb394c3250e0dae35ddb4d7ec81e9c8cbca52c41632bc5f98d9f19ae07a3a7987f6553e9256ebde39a71c005620f0036de82b2b4b7670f222e273bc9e335db8eba2a30c61c01929e581385c9258a74ca48db9e17a83050d508d15e90b56bcb314d229a6624f24bdaa8f9d8924133d477be367e1e08296e312e804384111f37d56015d8fbe3e246fd04651cc8a1cf3dc08e4de16ca1296aafe194c50649d00b3cd84c9df62fa2de0c767e272a176c91f5cecbb40e6536a617b224844e82e5059a09451d0fc7255be29a2313a7fe20241e91f798563ec798162563333b52f339c12d4add036836e96dacd460834ae22a9af01de8cec7e06b8464ffe194e1cc0cc0f7ee6c383e9d95a0074f09a5d35630ee3659d37dac64f691f5679523e921a9089eb92635c50d0fe5db5bc6b62f7173fad635d079a84554956c2cab0d849598a599be8aedeffcaa125f7f09e087d9ba719f42dc255bfc39ff003746419bcb1312a1a36666412888083fb6d52d4889c1d9febe50612bc6b7810fc0783db24db932e836864cab4b0864559ee86b1e15070f46ec788a78b595528e16f3b6ab017e724514338cea4c9d13c67af311fb6f27d707f555dfe6e3ce6e02342f1d137c69339f6288320bfc2422eb47e790f140d321e001f7769c78f012d5da7d7c233e92bc94f87a5a14e99404f434ca72597767fa5687a3bf822c08be4c50074efb95acfe17c9aa2c4efa752321ee43855233b5d08cbfe8466d8d5ee49a309a774fc1f0dee8cae4bd2bc1a10e0244c2666b7d1c3403493d684c25736530f8fedb765db13d6b8ddb48e2b37ef74be49d05b011fa011939992522708ea3cfe9bbfddec7afac4135bbebde6d09520ca27ad59f3c3339f6cfae32313ba71b231e266cc413f0f04d371ff1814b0098f8fb546629f909904b7f47b50de35f4424637f34a504f3c0c3632e81803d6eb7415c005b461ab2c8dca8f001306e713b5b12df852823fbbbcc80888ea1569f43c79ed7b9dcc0f93fde3eb086cd8af54de460ed87eec955a38408d71a15612b05773d0cda2e7b52f7096131b79d313489c49be7cb41a42e5d45aa68f06e11864d3b8caafbf4b32d69ef01521d428054c98001f94000b1b4e95a2abfc0249585c747a8cb8e0e8f5fb3983c8ecfa31455c6d07172543616cbfe8fcfe10224d869db5c6dee80b2e81989eb9d81d989ea7aeeff1000000000000000000000000000814191d2730373e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 39, - "comment": "signature that takes 17 iteration(s)", - "msg": "7600000000000000000000000000000000000000000000000000000000000000", - "sig": "fc0043f3458bcc0ee30362159a41ba7b70b1170b7c4d54b765ba97203e8c11c6c0c0b2f99521ba6abb315d37bdfea6174bcc21e86d17db34727fe8700e0152b837f36f9497e6f8a77dfb1a5f74a089ef95f22a549e18b776272149b9470b905d2ab1dd507e563937ba97c30769175c1b925940e655c82371e4a6d6c0ec126af56fbc798fa47020e951f0495b6be762e20045642ffc676b619c1b2a45d42d834c45e3f069045d5d186a2d86cf5d541d86d80d2ca4924f561553352330cb729106a6b648cd619fb0dbc9ca8ba992779ba84442ff4370b3049a82cb8d0148229fc6184a6f80ed275696b5ae5fdd8c345c3b47cf12131440f509b0dfacd71c6cdf57a916b988e859049eb12d3f35eb25af70cb216037fc9da6b9c50f217638eb114885a570d59193d9cffd21bda6ef1084aa4ad2b18cff10b962f6bc972bfc47e2279a3cf40218ef137daf397217b14e89ffa063f97fec61f483e5ed457c074fcf626d394e0a99d886ebaa8f9fdcc7b18583b120cd7f0ccbfc7eac1e72c94f6f419c7d4337d4f6136055d59ea6d33cc9f6876e336723bd465088d75bd11ecb784bd57aa3781765477ce06e7fb3c4cd48e272dd51ed82770a8533a2b6c25967d6780c383bcaeb06a698d4064b8236dfe78a0604302c0c102017600f3923dfddbc6a345e0439c86292f9b88f623a7a0c52ad2bd8725a442f61195d23cf32bf63739ee109e147ad7fbde1546a0a593d2b4a0a046cc1e8563b8446a724913822169d045a8bdcd9c9644f9c69080dd2d36612c3f9197bc0332bd4a552c46d6b7f76ed52621db714802a5ffb90f9ae6dab55177d7ff47c3067ac6f2a2aabf78a9caceeef17282b2ff482bd6ac104cec709fd2ea31a90c0a16a602a246818c2eb5e4d6acc44a16d3ca764d746c38dbb07d1e8d49c62ba13c9a0e74816c8db7f7d79efbf2304ab3b8ecf3e85c41767ca80e6e35d1d4ac0cb69cd816fb1efb442dc93f808920a6e93b57b78078deaee6a4dcff066516d33729d08fc4682bd31fd44e4abaf8b2bb87222e747b3c47a4a9fe753dc333f02a7ee46cbccb94f42dd3e479c079cfafdb92f0e4a1c2fad3c5dc8916fc5cb1d2e77394616604886fd457fa19de750660d56462466d0fb432815da8eff2e464a0627230222e36cca186164c190e7fecc766a0f081bfd6db069c60e3c1329ff4edffb80c89e8af2d5fea2b3918426702490be1acf6482e0d47c0aeb56c0502bdedb9b57707304abf6156081bdbecc57012c3d6cd2f5552214fe64bfb4fb5fdbbcb30f1dd6b3d133a9f8cb936561aa8ed5100dbc52ff023d822c1f62a1ca1954cda14a95fd23dc82a0d236f07e67f1aaec0acb08caa0505a7acead8014034c47b1bd9ede2bbeb283e5347ff520b1bf6f26351433a86fba6865e84efbf52ba89e8addd32eeb461f5153a1c3f21ed4f5cd31a3115d622a1ebd04e01a72db082563e2fbc3511b935c9f29d75977e075b750ed794dadda682019db11d4bd811ba5424b3de715410df0949e636bc12c6182d8e915048fa13570361db383618c724f85efd43fc0cc98a3eb34669cec6b7b73bbbc1f47c3389a22d216e465d9a233fdc575d360c48da5e4e57d12369f4ede75bdd3ff060f7822e5fe4fc90e82a6615cbf31ab8c707534deae46dbb2ab6f052583af7fadcbfe50ccd3c2f2ddef747e90d5a74ecead367f3dddb344ac12590d8fd6288eed560f0bff2067dd22be87faa36f11ecd747d6ab6707d816afea30f3f14c8c0e2f18dad90b928a049aeaecc024d0a1f8eb3bf3ff91c61838168b84519998275ba1b59359b7ce6fd448966690f56a78315a07c73c8cacddfc242c8d349502ab5f2ebce880ce7fa3eaac7243c541da560c87158618d8fa8af4813c1fb1b7ae68d68b9a66ec0493b76436d84a74bee86b4902fcb07c43858480a5b178df6ef17b2b67876743c9a2def17b090030191fe1de76575f490f942af0e03b1fe990335bdf518e1833b11dc2fd7f212f7fc60dad44116af849cb2a2e5ab83cd59af79e8f395296bb9ba6d302772a785faefe604df1ed28fd8f94408f7d4c800c7c73a43861dd819c5edf053866eee01c0bd18badfb2aa6df7758f976f7cdaaa78bc55257ad610c74fb3a542bed174bf1eeab7b5b0cedf931fb1efc250bf01b970e1e12e8df04ad05262f788595da0608cf12e41fdb9325b04d7f04989ccf6c082c115aa5a7fb3754babdb0255766b4db3428307104cbf70dfa6bb76bae8acff48c5eca23e5695773c9ab570954ce7fe3c092d8d7dc72fe406f842a72323b8141a8c15d2c76fc45ae6f5072edc26fe9eb3eab226f84f1003b5273ca66974e55ba5d9420ceabc52cf032de32cc351340696b5ae289cc9b669b783f53753150fe4ef1cc8c620c54e1d55897055bb0f035094f83fd8df3088c9a84d291c75e821df4d116134a43fc3bafc4491ab76ab0e716b3050bc09eeda882f058f702d15a2f63ba196eb81e94233f822663ced786e90dff8386beb24f728611958313e36d784bd3700571a1b46efa036435900fec4bb172d3b8c700619d26ddae7d2762e883a3b3d60dff81add52b6fc573a96f04e30fc36ebc01d7b3085004c2880ca78b6764f514ba0ce55d81796eea6c697ee681e187001badbe0b891142c6f4b3d8f6023e520b66a27d31bcf194752e0d0cf64397f0d741837c58056e344c83e6c723587fd137519a1febc1df69e68fc327bf78dedc2d4114f04be253641b176071117a2004d8ff4cf35b96213400cf729c303a888b2191ae3b422fa10bf010dd1104bd4fb83bb0d93cabc4fd2392248a02d17e3aa25c121927f066c40083d4dc49753a3dfc57fe15fc5837c875e210cf8eb4961b09ef7417479e59daefe7534d1ecd990e96ea43ed8cb2c8a680a95c17c80c93d7eeef51a3dab19a031aa49bd69d344532339f5a675c54e59ede9eb6562f55adea368c1c88a4736de19064b73004ab748b32d1f4be2aec13fedafc4d9bb441faf75cd97c316750bb12b1e0c2ba05596d3c6cc4978e9777a05c9bf81174b72200c2412c7dcbe078c86136fc5df49fa4b397ce174472ea39c709b2ae90d80f948e81b440cfd0235f327c6e88c1972b5b78156b265575689594e4abb553bdc614ee130af4a6d3423b474847c8a2b88c7b1e9663b06a972de58e9b2016e868a0d62ef2b306428fecec0f39e95e9d3742d83c9f661a72b314bcd90ed93290b05cf9d48bab69eb5c7c92cb1027253e70ec081e8d4bd0152f1907818ccf06d1c88bce8f479ae85785af6b4814810caa89e5305cc79775e7a028eebcd1e126889ddf9add3567eb36aa612e107d2c77e9404279e24c4a58e60301716aaabebd4f047cb87b3fefae747b9fab61143a59567f5db91131a27d7b4f1c2d3e65e89e9fb532d1a27e6bbb1fd4fee26b6a6f377bb3d3de9d2450c0480ae96adbc158eda557617747004bca80de84bc46416e507da59115185d85439d7cd5c99bfe90af883286fb032e3de080954a92f27efdbeb8ea64b1310709af9a05318866451c66de113e5eecbcd54f059112bcaf729401a4fa2038104297a3e12d12610fb84aa69da7fd71b2401b6a87ea3715ab87b2ca93487d293d145879aa200331d963cf30bb4b7f5ad2ce9adfb834a1a64899e7f0f103d7e8e16251420bd31863e0a477907455ab0b205cabb11d94c6ab4011493c26228f9517ab424fb5eb894848cd49a7124661403ee7a2a6d4d9ccebf56c1b55ae159d37e0e246bef7d1c3993b0ecf76a9fd8d9249510078fbe9de2dab34b17f4dd0296db12afd96b76cb8ec25ac1ae1f9852a110ab61e9f9662c383d12641b23c07c2525501691dde411078bf60142ab78a252e4116fc7ff36223cc2a2bf6348f44bf7bc91930ea1527e6687463fcc3e86032a6fe4653f3c4d0afe1124ed3b7d1a1d0838a4055d611f3ecf6559cb601a559d0b6e0ea97c45d769de46c0c5bfed2660933a518219fb16761a701673e6358595cce7061472b9eea287aa4f286a03fb3c07a97204c2e3bead36f0cdd71c2e184c47033221bbb34580cb044220e8253d7562d320f9280613909cfc6a32be3f0388316b461d770d2d8c8e2989318264551e2aded81677a90742c38b2fa6ce4e276f19154641c8310d88076c5e205158e1216f8605143e1b1f40da786b57110b08cfc822153a366008582329f95cbe950323b8ef9adce3e54d6d1538c75be3fae5c07d8a9953f5da8bbce57a5c3f77f9a5f824a5f0d74bc1aa064dd4996e53fd5a97c513e0587c49b69dfc6c3b0d6f508ef44b154204d2126750c216be1370546b97d4b1421296ab7ff585a9cfb8564bae70ef7ea96263065a1e2c426a271b2e4a150de230b5a3f142f2b6e74f79b1854069438fe53aefc18e2d37f05fbd882fbf9f08880349b1915b99e537dc625c3bfa8059a4666667351963994941bac4ed610d96d69fe5cf33401f9113f39c18031703faef7d7395ef69c1b1171c724a1b47a189c0c3dd6f7a2f35117045c0fbded3cf41df3325228213cb88794c186312e1082e6f0b997473854fc24a65c7968cefd4d30b874d6994b21fc4bc42d2e5045d631150afa2075060bc116d56712faac07ec354da67b974e34026f13eecd8cbb2a8ee011d2f30b9a6730a8f552b6c3e45d384c9a57fca45c3f33aea19e7aec98a4b5010bce692f31f19925b1413451badb68f7e0bd34da35e04cf73b43f6732b9bdfffb97f8786025587cebfd7a6115e4927030f88439926fddfe7e0ae38172e9ff3536f8473b9a227fbc52256fe3567778108d27f2202877c60b81cb6f79b3a77dc75a7a615b4705746497a97a0aee33b2680b696917754afb09e0a527643182167a0a6e03fff8dffb51be185bb09224f9ba1044cdaa25ea9738326cf97949a1c6eca36eed94b55f51c90e7bf7809fb0cd066d70f1a74f68d88b534087915e2ba3c3760db0624c66b4db427e5214447eb641904ccb4c089905acc59e5e5b9876d68ef077864df8c87daf6bcc7896eff7f7725a2c5996333dac087cff929ac3f6d835f86cb2d1eb085ccc5514a5ba6d1529a30fbcefd67a2a4dcb7eca29aa655bd45b8579bde5e405395e037a63d26b49b5a38df89f5c749fed6227491841a9de7428d37d923314b0d8023bc4d004533e9d95fed5f6f8a6a7a08de9730fc630717567854d6bb3cb2e7d3cbfb83302e51f1af4c9baba07c55e537168ca64b52b3fad618b5ec51f3f1a936ed0f322de5ae500c82401bf59a7c9c5cd31e1b994246d7d3e3f7bc0387f0690b7e5b6ba2cfc9bc71a6516b4bcd16ea62781586228abb145b90bdd8bc4c596db74cecc78f96a2f3479f12d6190b3708150cb984ed502a1a67fff4268135b6a35e4d2a4e3b54f4bfb80b852387c215be35e9e2012095a2fa0d544352de7311c606f16bb1da478cf4ef2f89f48d25c9ba1d785e42d6d2530adf6cad9ccfa3478742d65cff2539a38e2387051a2bb0d640ea034490786006760fbbdacb5c4eb899abf50ae73bedc6eb80160f6b365361b937acf3f7eb376e08129320f7674f89c8bb3fa4d821ef79ac5bb57711bb571c021803aa9a9aefe84c0f7c97fe1c9bba1ce7f874e8f96288fe950a1ef11dbd890ca7bef041e5e88fa4f0301c0693151098fa5d9d988de94e474b40617a71f8f13f2461691528b93b2615ee89992c92c5fb7981e11863aa3c8cd1ad19e934b898759790b1d3bec9612d64cd175d49b7ba2eefcc8ac04973aa33d8c06f0e9d0ccb702efce36dc0217c9633a268dbe269fc5e4978a8b99bbc297cd8931586bb65cd759cbc254ed1739c40204bbc9d574fa5dffea7f908dd794c0f59c2646a730bbb117652b46cdc040c62b750560b560fb9c7fb50e8bb2bee4fcb46720c76abf4849eec6bd4b9ed30217d0ca9ed6930ea82cb5fefceb5ed7306f57be786673c24ef741a5278f0a9e574982462b0c0cc245f83b2437c997f94928eec9c85753a49ebba16943b826ae9f437175d227e1a8f3c083b769600eceba579abb38ae8ffc5868ac9aa229b3deb01a29c4bdd6a84025db6e56ceeab10cc31ff0e69b872f4210de70897f77574d8b63fd6e49af5d9924da079581d1d81ed7f117e225d8c35c6cf6967fde67422c90b8ba6b3bcb4e7c19655e99b8fef6bc670705208c902f6fe86949d6c6163d29b37f38962853fc266db132fa18b5ee576b7f15a0c254d0124ce715fd10dec3009b5a21c009cf71133fe67c897e9d2f7a711f335ea7d0528cdc16dcd5b4f86fae8d6f85b1b4f032a28244a2ffac56ba9141e1c54014cbf8e526d2ff97dd8e483e478e83baae795abdf09112c8212cc35b7c7ed9275b5a32e69d5f5720a1696dc1ca9dad1155b1c2d0e0e812e88655f3de00f4ea8e05713254ca9ac4b6d48ec6c291fd023504e213c8975889161bfc543f0827110c84304b94e0b72f81a233d485a90a4aebbfd82cce62363b93c7c88e5e8283d4fccf6087685cfe801142a39586ee2fc3b4682b4f1f80000000000000000000000000000000000000000000000000000000000000a0d10151a1f272d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 40, - "comment": "signature that takes 18 iteration(s)", - "msg": "0801000000000000000000000000000000000000000000000000000000000000", - "sig": "b4a33f08eaffb4b2092c87da07bbcccbf0a6815af18eb1acc857ef33d65069252f8672b5a37952074156119affbae3ab524c2bc3e2bd6e64d9f7a2c2672c373884325d60d5015d4cde5e05a4e2d696808799c582747f3786fea3b1a3ab198a54414a7bfa3c673b9a6a560884caa9a87384eb7fa1ccb34e550a13f45430629889bba53d724039e9c9e0858cec1306a9414947130e24f50cb31c24598c3ee50e5273e145fbaa1c232edd0583ce8789064af6b54d8500cf318729ff0005427c9f573a087151bea4b38519d28135dee555a09711eafb672ca39b331a22cd197801382b327ceb7e4db33cb0933dbedd467cd24e5b3ea826e1f05aacd9de8087d3c8f4fa0bb25dc340156fe150abb2073448c87dbbfc9bb8ab9ed4584e57ec52d44af9eb2d6dd0d5731105c7b78ffb55573a00a710d196f08b36af061dae91987c5fff576535cfb83ad1f67ff59a56aaea1a3a0eee3856c0be6dc5a49dc513e43876a3850d50768f7a2a3e251a42b1ea33c9bf6d9fd9ecc4ffc513d07ebc16456c4609f00aa790585183b5e94acac0b81595f91271b3a61bef0aa0efc31d13bf957defb15bd29b2f906cffc61a7eabb57095eafc3394605403593f5c92eb9dff39b241726f9404abf36e7fe2b780795749f684eafd84c8314b7943d0a2536a7ef12e2bbc2eda25c4f27d6b4320034a4b73408c9a8d0ad3ac4b84b949ba253fe15926dc1ae88ae4976110da8a7b3247790a133d0f2827d5e94b33a9dc7f14ccc0a6ea1f552833471d604ed0c2f566225392fb9f920615959e585ab9d9e3b1154342e25b2346a7c25e1fb086a2cc1ffb168f885a33480ef9b2d60c9771b37874cedf55af61b929d01d7f8c7d6370df6b9f3fb83761c292b7f99fd062f3ebebfc6d5129fc9cafbd0f69175b5f95ed2d3b287d1eeb0aa3a8855841c5e6b37cd2149bdb43393d79955f4d73051fa7163373ed1f54202e5c3f9e122b525e0abf7f38809ce24a0c02cc3c9ec33c581c51d7409fa5e08b046947529d78be5d91cd81a5c23ce070fa045a48cba8c1b90632488c71c9048560a4a50907305b8e777315956731de2c734580a4578d7306e4c9819b28964adad513d4242314a57d8fe78bb29e07612db7d6d1862dddc9926223de5b814398ed8c5f87e90cfc65b0985819e5acd89b385b16ddadd34d94f59fbdbf15e1e39372fdaa232386a0b619d9c29afef6fc44604228aab7d479db9fc02b3c91fc2e6674fc1c625035bc486bdcbd8bb62381e8691fdb8ccfd59725acf512b13f5bdc1a683096871d5c96941a67bd5398126b5349713bf074432714d9926f1f84677cf549a1ec4eff1497ddb06d28bc9e75382524d16a1350c77de4773b55b6421ff149b82d5bf8880017b12fe4d18554e36d274d8fba310642ee50ea28c08d40ff401069d0e0b575135baa35e31131ed62b6021553219ac1569301508f2aed1975a62189750fc99fc4b1f4bd69b224b93ca9c94353295fc6162a38fb9318ca9c5a2a415a70ac7a031950e1665cc4d54694c1da23c51e0987089971b9bc3a72ad4827bf470b4d97aacf6eecca5648cd694f2f439497975eb7f711cb75856e627e6f2e1fbd24aac92293f4c6e7e47d05d88d6e321c3a775895ef36dc838136d742a11712f4e58508203b1f0ddc53b1ffcf25cac3a6e0facd738ced5aa67576e0e030091ea5e9f0c21aaa7328c797aa0b3bbd1e56c504065a068875e861db63a6e92dbe7efce92bdc42fac5d71c0b0c4ac32ffedd84553493f73561afd1a1896adf9368e1a18248d6594dc2fab159d497df46a4cb35c932edc9f32158d9ea9a1b1d116ed64b3f3c695341483d8fa5a37f3b0c837675a74220cb588e08f3204c1d5c61216a82c9909eea79f0192b72c0390ce7839b07cf90b41b3ef9cd1636f5fc9426bf8df9a16f98c4d2741a6987ae1768e05587698b335a90857389dc43dc4d5c93db9422c9eb963766fee579755650b11f328961f30a7bb2f09d8afde6042e938a7b1e175a9aa6cbe9b49fb636571d22508ac8990b6c7f36e37e40df3f4d627c93de611fa1ea5e661c0beecd22653aaab997863f3681a9eaf5d5b6cd286c963880fc39125762ca82a8fa694a60e96f8c581de570e902b490eb884454d31960df284cb8554eb76ac053c896072beed3888f35c711160609aadba40c3613f13b88c5c86b4978f0965327372cf7994d5e5fd11006409e557ea01a32b8c1cd2290c09d4dd4788d5cfaf7740e543a8b9efc3e005873ca1434c7cb90e0b03ba8f46e1aedaa989de874bed1846f83408d563302ca2ae74e64ba051fb8e12621ab57e2768f8d8a2a77d58f592af156eb6df43c85bd21e6e5a50d6850e71671ad7b0fb72b786133e00cee31f021f18ab7c1d64772acc43ab4210650b692fada9baf4afe792f472b86c30de5eda105f0b1094e457405d9b8d8525357e2dd1fc4936068da3321fb3da7662f2b1b257c717900823360849254b7c815eddf1a6cb3e51a74361cac1d9558d36187ec929780bfcb299518669d85f4ace80a0d57ff768ca028b2508d938ed4d5b7cc9a707fd4d31c084ca39c28e42fc0024de5209b521470b58143e810df9759ebd0e378dcbdcdb2dca6558742b7f37ee884e241d6063e336fdad3a881096cd3730a49e89bf712791421062661faa1e5cd14483b7031d10548ed90dcf17c1495f28442db7a9d3a5c4e18802301fea8387c803b8169720850f9067c1cb739f7b107a30bf6826adea1f2c38932c09747c7edc922e520df9b33d85e21a1dfdc8f1530c2b6b00ab429f1b961cb51a5c668da1a7edfe9aa60ac98b8565c579d591876128c770ca29c58931ea4b990b8dd79f870e09432508948372e297579d0d31f1fc0208d719ba725a5995e9d0c076dfa238d1779f8734651a18c57a2798faeed064a9f099918fe7f0af4baa8f2641b4d33b55a5197669e5c52c47165b565f8564513d899cc372d65ee4ef931a9ec56231f0ecb3160940f92f9c650ee7c5b9690a2c72ec1982b6177c9b33c4b7521dddcd57a66938d783e563e9e67fbaa5dd49dbc4be693fb45a25983a7f835d798cdab2dc6fc37fcec27cbc9fa29bf6ef9df1ea473f35b8fd7017854046d611b86f194efdb240588f63219d48b695588c46c362c4c3981ba64f51416e6b38470f9663e2e83de65d8adc0ad487e26b3b5f12dd077ca5779df8d650c8ce8b1d8e88064fe16236784e6f06c6a880bce7b1b7722a31ce41a5e2ec13a793d272225b3df18eebfefff4cf56bc80d467fa75c330b76cc5fd77d8865ff696e9353e4ca7d119e36707b6d58e5e6256b96861dffa20e5a35fb173da143cc26b864835a7241d0be20cb6ea7b93bbd04446d784db3b7456277ce1fdc12ec934cc3c88b9f5b6a3c98a32382513dd002f2f797bcb9c275f08fd00d565b96631440030110341a9412c58f4093b099a2ed2ac5194e86cccb8bfaed759cfaeffbc97f9ca01c2f949784061d08fcf21efe8f8093ade05a1a3ebdf4c1d49fabdcd5135211332dd136bb47ee36740c0aa89f2edf58d7338a66793a67b5237c2b3ed92a1e4722c343348fcaed560110fe1d00b5ce489ab76465a6db101db6329b76fe2ec54bf7dc184ae3b63dc9501a5399d8c88d0f7842045d3c344a4dd92b0d89052fe0e596a60883894c4dcc830076a11f350f20f77ec75aa8f9f3d83f6b0089bce6cef93d4c2b773aa499a09fb2b48d964b9a4321010ee4f60548ab2a503e4abb45015434318fce40064c865cfeb40c3f3a6791585abc445d5673f6ba08490ac06926111ebe4a17c6962d9595bf5f03ce5e9e36ea2ed6867bc907d7fcb155cbe6bb069782aa55f1125ad58ddf085e9c59e800f3b0add3281c14023762ab39ecc898a284a832772c75e47409b1e451c8eeb94e242f6af569abb97817db18222f92a2d6cd686b647dd8cc944aacbdd224e0100b203f49ef0d0282583bd027c0a817707fe625c9a6cc4238a7daad920d3dcc28d1aec85224738eb0d3cdfc2fad202f9d117d9027923dad1e56ef6af6ca8ae81ee3ac9d84d2d40cca7dc849aab29510d735f9db4e6eb73f49e634e4bc0f7af9c025f68df6f6c9af151a7211550ff77f247757cc1791dd8b54194f3301aa05cb562c19b280f800eedfea2645b8e5fbef7cafee2aa61b10567cf887c714a34e5e53bc3662c01bc3137853d6800d69aa7a6fa03068f309ee3ed608998883d18debaf8453e5d4c9a331e8a96619212895f3bac85342ea18a5b9359f6c76ea294f78aef65de75dd764b09e501ec888b81ee5570fa8476694aaef2fbd4371aa397ef987f33e8fa7372fdcba3b53a63b9d11c78e84a7bbc649e230b2bef589fb2844aa3c7a86ec40c37da9afaa512795d4e720d120c1b3373cb6706151fbf60d7c284c614160ef5ce21f40b92bbabc29a15dfbda1eb3c89014c296a5b6e0298182e3add2bb0a9dc0b28068d7e9c9270e839eaff9716b5eef8dd6cab70e44ad3f2bff6815c039267839fcf114e6b0074ba823f02f2a6fc7e83ba160cfcdc7ab376aa8603ac94e0b3c0a5401bda7307e4d5fb39b5689dda2a401955fdea5bce5ae3497a27840f010037eab4946464fc2c87080dcc1761aecfa088e0ed8415e1b26dfafa0d77e285e27d12ba5f0665e9e40efe632aad381959d9e77195e373d351eea0b5708491f42a7f9a961d9a6337f08595347df138fabcf18d03a8f5c256532770dd05c68368ba5bb5dc4af4dbda6f1195e71810e073dd013592d4c91be62f5ca876d557a1f16e883863813dd26baf3408d0dbd4af303224f9293a3646f2d793d1f459fd80e3f4c70337df09b7035738e8e483d9db347bd82fd0d005e0a76d27fcc04770138f015d0e4cd7710147dbe09a267571e89cd2ded9bbac9a0296f095c133bdceac8bfd5ba9907052a6c1d12cb946e65d878bb20fbc8e1c18c535ea44319c6e190190a6a048e6ae652dca3da14bd007b46b1d03fdf885078a0b2b56162ccd6b1cd544a43817305e13f59558ec78e68efb5a6dbc61afd7a1b3485c0b0bd119652dae317ae47ca865f13339054ea3d7e9b71fb01aec115ccdde1f486e61d05771d4442bf55ebf50052a217567284e520bcfaba300d6132522f6b3d136bac1fc7fb225166151137db58685ee2ad3047a558a77a0b81ca009a3e8f2fcfe29451dc6907bce120101749a08ae43bb161a03e6657b0ff5663da1034f82cea37a613910e40327d3be288612e5180c735879f92832f2dad3a6c8ddcb0aaf8b04cea8ea64985179d2b1ad7d668d7f08fae72d06961e27a4be4a3b7fa9373a22d4f1030eaf8e9d7f72d4d65b84a6681da29d53aa006a97a88a6d8bdd7442f45e43ec58e3e66b74eb05c1550ea259145aca7482d7898f1f04bcb59016c4f7af0c2bcd5b01655015dfb5a5a1a50ab2a24e5cd21ce40d45afbffbcc295a110e8e69388a1d164f7776396177580817da8b9f03f92573e4b9e6b6b4db73850b9a879e8bfc12d3e4c061379366428f9adf8dd1dae392d70013e86ff788baa1bc5ed905dad1fbd3ddffa40dcc5c945baa35cea41352131e4e4e9c847e1c1e464f2f800877164cc62b2fcf25790cc8eeba44485d2e479473525fb7a346cc3ee92c03eee371df1358b2c21921827f5dffd7e35c982220155437c0580e820ed948fb9863ea5c0d0fde59db6c94d1a5b3d51f18507fa106fd3aeb3fcf81c151659b70aebbaf220a47958f6e6c923b2e240779c48ae9a4bccf8c02ddfc2d54a68f70a6375962960d9bbd1caad721ccc1189bc235ae66a8ab6f9f50a65e63b6d37a75296793258c0407882b5120c2d0a4f7f97f34553afd749c71969eb083f676edab7fd9c4673eff8b6c0c7f4b7ab544418de6719edf789beca0b31a07a49dc0c677c3cd10a68c57426a3f8886c2c8e30416d1cf88df61683a00384e6d48e1b6fdc9939dea0872f2063156011c6dba9ef1c2e5791d2773382058ce0c9b665bf1317a044ce74354397b88167fcc02ee313eda73209577f732dd74c3dde82ba59f2aa25fb7f32aa6b14f36bcfd50ce983b5f5b5d2bc3054a4aa3beaf66f843a639f27bc2313260aa34178af8c56f54ce7969ce014daa7d2e49dadf8cbe5f308397125e42d3cbfaabc8e2034b0aa9a8e803289e1b043f334ea2519dfd6e22aa60f5bbba0de1179e9cac04ce95114823f4de59a450c47c3d60e960d6d766779c78ca5986a929cf4f139fc9c61f831af41fda83430316e79870f8ed250c50eed3a7bc90225698cbbd62597221dc940df73e7562fb5ded810b24990be6ebcf545a25b00da73afee6988d0a9009dfae2b4a455e31e11d0b5ac7cc49976b4d498806eb8a8cc2c10506898ff9a36c9c601fa8c5435bb8282c4eb9612d15b4229e4292356e9f15776cc02d29e08e147026a4e0b0ecc3af904769e2897082104cc718098a3b0f553e9ad0c626b8ea4afceeb0f2034848d9b47d0e3333f46798292c2cad9e3f703656baa000d354f525566767e83ef181b1d2962aab9f82975777f9e9fa9aac2eefa0000000000000000000000000000070d101b1f2a323d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 41, - "comment": "signature that takes 19 iteration(s)", - "msg": "1701000000000000000000000000000000000000000000000000000000000000", - "sig": "509fe66881d6f2cf689ab78406d705c716bbd788b6877136805dbe6bc129ab5bcc31602906e1036e6fed7d5d18817085fcbbb0a59dd258d14afe6738d95a607ea43550a303f15292b973f557746a20d2f802a4828cbeb6959e77e2f82b037f264fe2798634ea1b71f64c0bb694122f39c93a57eac02c84a3a62b989a3aac23d866175032c5c43db4fcecef277f4180cb069a89d85a82c5d13d9adcab4d42b3b4989401bf26758d04bb4c86f0329433b3105d81bf0f3a399cc9467f98fbd624fa6c082b5501731f19717012b1ccb1d3dd3a2380bfdbbb28a5c3a32379a6243f223d8a9866df80eb138c4207222eff412415d9c1aeffb559d90148c41e3886ea02c7caf34e5da766af0715e2426bb49da38037be370c0f0e08795f22bc6636ff174d791c44cb56378f53cdf3b6923e013ef1fb753cc69c5712a3715197875d5d5b4a6fc0a06ef370376899b8e39372a75d3cd450728d4967a90ffea898e6f949bfa4c07e6f0a55d65d42a36af1c160e59c72436b39f0ec95b4816aed598939f8e2395dc95bf2a5813f476f8233214a1994588c5c4b7ceee052584ab716c2074eb4bdecb19cfc867b8147d2adba50a32574d18aec7c7ec4b49316666b02e925d3b0ba8dda8e453ab182f6b0632883c3201c139b3953a45c4ff10d1dcec6481ce4b8c1f9764ea93dd4adcbbc0b55e16dcf77fdf00231ee314064abbbbd3ad1a8581303be8efdea3b18a0367eb939a48f9310891b8d6c355532a5320bad25b670d29f61f6f4f1a7fd1a28e2af1b1d263b2e6e75736fa0973c39ccd0fb927154794dfc8431a7c8644499e556230a5d86a75becad173490ebacaba8c7bc35a8718976841aa5de36531ccde309419fc69df2e85d48a2bc01df1a42ced96968a8bd33eb49a8580447832af3fa6252fdee466cbd2f004ff0452e60f54cd5543b0334eba63aeaeba9e4952c20ecd68d00ba86d165bb39be469420b1aee7e4bd184406283f026b28035bca82269d59196e799a1577cf48dfa1bc203192752ce63dc4168069e17ddc4a6b91acf873de69b72e64b465eae904947627864215e78803362a7015c4e4b98f5bed070d081a8ab6e2a86032913d614b9d25ae3fd7698763b927db8c4c5bfa69f4e262be0f9dea5d007d74b8d20890353a1ad8f8d92af57a609735dd38c49ac43deea9ca96a385c5c7e60686261a458f1a7f6354673aa8f62bd862211a4d4e4057bd78f2d0514c48fd67d945317e738ad8c5342442610d48066affc1d5c5ef3fe0c3319df608b1b4a7bcdb3a2f365ca26ccb38edef6629f0fd51f4bef89c909fda19e645fbfce91ac065bb0a23c2f5adb18ac55cab401873f27677a7369234ca98ccf0a2a9365d5190b7a4666143b19306a828cd4b9160bc6fd8773058af848999f87d420fe56baa05dfd2ef7566c312d94b04377ffa036a36817e3234419522ef2abd8aac0a9cc0e5a247c66f6371eb3a22ce9cdda045fb9414ac3a8030b4da03cb54f26f2ca55e077ca35b23345d4ebb9d50dbe1f31bc8b2d78e09bcac0f05252abba2a0726d4950809cb86042009acfc7b22475bc854b680e9af07ce16140739b62dd0857dd1afcc2202dc358fa94b2308e69350a86cbce6dcf2354500f60a2e80bc5000ac138d3bdefb127c2b9584d6ea1bf8bcde7648a0b18775c65b62044e3d031ad14ab40e7d8ecf86a251005945bc006426dc941bca6bad5de69295f6b7486dda3a61f88c30b714be911db6940e2d7315101d692e2dcaa3b40f38a663acb83956c9fe2889c0717c624c2698e507b91186868b0749ee375d250d43e798d5f97afe118b2cb270f512ce3edcb3a4fc9367fa00e6f5d81634a35181d341ac8f8ec1cd436e848f15a7858b23f6d7ac2e92733d0e89d7b456a412ad9882bcae3cdc63317de81d4ef3ebecbafdfbbbb526a9fde90603754b27397c48b50a000df10646090cb2bc832719f14da8bb3a80a55a6a1e16c8df52ce3ef4f1485199a17dfb422413cd6af8dce33181d22acf015acaac9942ab2eacf6f10d8d0bab1835519111914688335532fec8b0e6f15ac4b32069334dd025e3f9a47cf0378aec000d9cf55cee208eb407b5b97407e596152b8d93b8c0ddb3b2db05e7bcaca6a1247a4fa269f50597452b1f1ea0d21c989e39c536d8e4915ce43238e55290470b5808af5f3a93ec11390e7c3603c3f9b9683325abaa3d094c3c27b5770f13a6ca9062b2025250a6a214474e2c9b4c23e9ca5d75b826a3bd3cf69969e3c3e5e55cc44ea4faf580ef1994404de657781f1d56a5ce00a2aad2bedf1d22025aba10ff051d0454c7a3c26b0ef74f8b9d29e2143a97652637e646a744985b9ecf10a0f62c29624c3413a176f0cb3336cb8053c9c2f41db29422e00f422baaf16c580c63212bd17617c002ebb68a84f26adc41fd6ddddb3731f86296191763b8ea85af5ffae5d49b22cb4c5715ce4b2370da7bb610336c6c9a5c6c0fa2b691b588aa20f397b366d685585216a0bb87b4b22f79ba059c4abc455db0986c726339bf8c241b185b90d24f7256b257968bbbfb7587440792748fb4e4c3d46d33a1e60e593d30fc0849c65eb5bf1bccff42ca4f4d7e3c21b4dc6efe0427ac7c3ca7467b368853d38f47cb15f6b2471b036a548638b23032a0e522d78ba829431602287683726414861a6cd9cf47964efd519cf70a574621e76eb5630d95a4654bc191e22bce9669a827058641671e4048ef910a9e98a7228ac73fbbfe430f40f3695bd753afd4deb43bfb6ec95b8bf3d8cf2793e2834033f4160b0183851c3af65be08ee5820d42f7192613afaf4d133e65fcc4d6cdb6d0f749073279b5f6dd91943c5628a1acbd4911dcfdd506f366d2a7087245c6c4a2b5f24254362898f89be11dcd38103a0c497a7c433bc2c73859df896341174a45aed7eebffdb2a4e81021335c01b8e2d2c7916019e23a4558d85f68c6cbf86c73ea45277e27b4218d4efb8a1de3894e95e9920aafb90063b7abee8f77d74bb1f58e9f1fac27a0ba3b1cbab860903766b2e1c1e40302c083e579e5836c69742f964c5a5bd289d3ab797d4c421dd06d9068dc55ddd241ae032917cace7ca183d818bfe87b77cb42228b2931be09567549f49bccac491fcf1351e8f79ca269ff0b1c3a040757be056203e3a35f0e2088efd4745e5459d5c313e3f80c898b332ac53226831f527dd45181b6bf47988e813823d6cf482088324f5a34b99ba5584e65d4f29d042b63e60fbb127a0ffd13aa02254b55660f9de0d96fa1894497b9a7398d25cab40b7043e17b61f6f0cc32e7a0fd674747e19ee77c03b4413a83b3ce23ea69042b48ced28c7ea00e560bb6378f69757bdb307944b6bec110c41ad03c3e43d90cc2f19f51033a799807faa0edad997b86f5c90583b563a42a3b29eba0e1f115c490dfcb7060ab496e718097bbd21d27a21b6e85b9b30f3ae65650e998888c7f24fbfc772a6a448d67e56b19ffe9c30d38c29038f4fd393ea8b07bc3690656caa015000152809e20987ecf53ee94befd35581308828cd8cc364779c8507c4f671cdf3b2cead84eef173ef382715267b29749dccb40780db14e644184a0506c4b9af97a20c3f7da25b7e31f7159d0bd6ffe7a6630b851bfd675a3cf453be2e56b22e5adca521bf7f8aa2bd9662a6d2fd81ec489c80ee14fb0b64dbf4441cbae2bc0e78684460eb311de854516cb3d0593f54912a190c8844fd6c649db9e6193c2d84cf823c276341ce78bfec9b58cde37a571e7161505f4c17c07c5b1e83292ada40d3c2103ea75b5e4ff9e763942af9034ff4a272715d8107404a24881bcddb1ed045df78ea34f6cfc301eb0ca08ef8c26b6df4b7014aa3a6ab92c725e7ab07d94c4e8b6f582693a8c022b791f117314c53738a608f0b9525b9b17ced39d61891431432d12f8fdbce5d3d0c09205434c78a95f4c71d6614a8dd7c64a36d3cf541f4b6641aeb303da366197e38615a94012dfb0b3aa039ba7ff4c1946fc170f92f9cc5283739a3bc13b47b384efc0a7ad706ddc3abab1f493f728f93fc5a3e209c353a9e23cc1f9b537b1c32a91b558255f3c9baf37ee1b1444ce2d711c4a2fc038e8576821595a0959749c8a717fad8c55471d764ab25bc2d2aa37e8b44ab108d3305fd242dd2c4c70c216e6b2b9ff7ca1a4b8fbd004bba5069ced40dfee73b11253a1598b926fe0ecb0168037782d5f35166e60ecb133eedd5f13b84b25544f9bb4503e3b9d6faf85a9fbcf371d5f994adae1c17772d1073a5014ad18ab66010667b2a27ab801eb605eb4cdbe53c749a9e1f43fd32127b193f0aeb25ce9cd2de6a860298a35eec0b04e7b8bb15ad453d0cdfd197049bb89f526b2f54ecfd20b4167503391fabddbb10448dc1817c2fc41236607baa5cdfeb52414384308045d9a5186b8cb809b016d9e95b5ad62b23b48896be028463710d9d1ab2ced443420403dbda8a919c6b54c70e67a3506318dc37e148523a6e8544d6635720839175d10370dc4f463512823aa863a2922ca4e41bc1e867e079038ce1205f586089fefa2e158495e326f72d348b1672a2741c31830bcb31818be33dcd3c57ca2170afe82b77612353621064863c8103951e61e34923548bb6ad437e07021adf1300f0be72ca6ab73541284abbcf40e36c443b98a15fd896f94d91ef6b614218ea5a283bd73ef5e824bd07124986a522a821d110306ce932547434f324215b3dd1ec65ab91bd9cd1239e7dad05e90254583ad5293fc17b5fecb693a497e4ff05bbed749fa48b19615defcf0e5ba1a99219b4ab4fc564c9a0a84b6d94956eee8fdcaf3fb8c11de3a0c8fbd31acd2c6fc362424d5ed4abe274d3676c14497ac78f1cce99cf6c36705b45acac0f794a09ea576bd07b0640dd6db4e99619b141b1ef4433e94bca017ffb969f6a278ab79ea0d6f2b96bf13e4d4b4d2654ec9de71a1a7c0f86aa03ebc43acc95bb047a4229068e6f1baddd3d0154f3e31702948211f677fc10c9d3691ffe58ec965d1b65ebb0cdcad761c4484755603b208434b54b3d17b1d3cb93d444100e7bd01f22f2f6e09279525ad4f7fdd9086431fdf5c5b5b454cc43f82ee92e21d060dc2550353f45869d8bd29c2444f8c82bd50f7e67c86905f6536b0094e2e04c9774eb539ad5c96b4b0d6614af283f36a7e812312bc1e64d0e9a4f474dbca287ff2c6d2a7ab9a286cbf084700b2eb6d74251a2588f8877f7552da26acb53155795b0bcacbb4dd3e1c7736eecbf584b1a408dd1f1d1e6405b3d6b5512c16ea67b32dc77bc229de96f01a4ee0098c204712f11668a481df9d231decef7422268802907bbffad59f37b76dc1ded6695ca7c60ec5b14d856d453cc73bcd164e28ea913300c8ba0a264656e90e6f14f2b7d09d54569ff1b7d555d5de99dff70491dab8de8568b83c6bed662ce71bfc406d8d0894ff2a2c80e8f75ca826e9b6145a68214a9882d45ed4e72380b72d964456bc12ea8e67e1ff96530a1999d66c607b4a147721d19d97fc60c049d71269014f2310df5032a2d27d7c19acfde1eb0866bb8e750fcfdb7f272ebd668d6a2261f979fd24cb7c42ad04d1d2e539922a7dfb6af2be25a988e787df8cab9f5935cb9e12f769d913c23a48d57ce6f22176c324cfd7922962e27b05bd6bd98768d1d96b4c3b5259a0fc14c6d24408d67049763321baa1f5fca459ce33edaa365184f4dfcb454992b1dfc456bc89d350f297de16941b8c36a4f4fc0a2d54c125900a96d4ef4e4921d608014d34c4083c98179c3a5f01e77eb5d21fe3b98a513fcf85b92a37dfa5c444bf725951e7f3b9fa1866d9559d930010e5f5e4277a7e5379e73c2dfac9512b247b6e8d68400d633bb365341751db02ed512f76543a505bfc5e1eb3ab1eb27239b17a9d23da8c6d98a0227e2d366dd3bc9e3b21d891b2828fc318602b8987af7aedaa8538ba1f6df11ef18af80ebe80143e03b438b154166cad06ec34e8584c0df3f3ee827079ccad49e358836278c2b5b81b8b8e27cfb8bbef24842f26fb636465580ed8ef277ec43111526fb506f00ee3102400a4e60c4be12360b2a2aa2a732f72b1d66fd2014a8cf68acf4e24863df6dc8e239a0aac95508810583f76c61ee1dc5e2d8a484101c0ed40804fc216a8ad4fdd60224ffd2dde663a71ab70fdf83bf005207f775d369d3522160bdf36e8a6963e7d5d9f60a3cea02754c6d22d63a43501977abe58a27e24d03fe75fc41ff08e73b2b2ed6ae76271082928a9597c2c23af8a9749b967e6ab150d10379b2a80864d9f6a01b6b926e36d044f5d36dd6fd5b919d1860b04135b3e7717e26ed00df7e78372a4639300b11723eb6230759720b1128aca88d54677f2a674a5cfbe9aba80866c82f6e8fdb3c558837ceab6b3697baf4e21a0d88db49f4ac601a08f201895868939467727cb2e3fb090b12287f8f92a7ce397b7f80a7adaee9181b266a949fb5bec9d7ddfc3e898c9ebed21fa6aab2f61b252c2f333e426b78b9d30000000000000000000000000000040a131b272d323d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 42, - "comment": "signature that takes 20 iteration(s)", - "msg": "1c05000000000000000000000000000000000000000000000000000000000000", - "sig": "e05bc77c5c3cb3eccdbd0bb2664eedf3ce12f297192eb57619747d12ca3fc7e585b65a47e00abfccd9f49ff743851eab4a48a6d7a949eca3db7694847a01321732358b83b3ac6fe91c3df33019702ac93020a8261a608a08378fca9221b232f30deb8af2e7fc573b6f33d53ee7dd7b709b830e0327323fdae7b082cabec7c158de4d41a8432614476f2a91eea53b2da0e4478766b71133744947d92f49763a1212c825e4a9e436376427b2a22a574afea4df6a2d01bccd8af2e6f97b2472a453ff9214cff1caead2096d77b95577d98b8363eb065c7eda14586865f7454ff69595755d99cd8cb34b7cfac865b61ba1481544732737be1578ade7e0a2d7f2b53246800db8cf8d484f9d5858b4d224900f77c5d8893b0b0fddf82da17a33c7803bb3a85a9119312166890c9a297f2c6f86c74d475f895ab17bdc7e6de014e089acca44fa6b5b603db1298352f6610af49659e9473794893d3c1ac7ba0fa0dd9e4b52e4dbd827ee55c4df4767b9f6540b143bb792155f27f0e439e477bd636e7fafb9b2a517536335135d5ec5385ae3f791803120adde0f6875d95f07fa3ce58eac39aeaaaa89c123ce3c72984adaf5e8e08104cf055c86049f78c6d1a61264cf277f4503840837166d8125b1f2440b84445ddb8dc18d6cb123c036353198e9d9c37d13fb916fd3324c7cee56b6e1086a480dae2bd1a9496bbbdb49a72f05e5b62568fac561fbd6d6e2edc743c16c587f43a9cfd2ee74f73a55b9cdef5a2080b06b56e1435f86727eda99c4cbef4639a9046d1522d5a0e1925b391342b7196d43a146a1cee41cd81831c1f95318b925a10548cb1bf9306086ec8cb3351e084bf9b489bb89f4d58138864f794e3b7d265d610ae1ab03b7fa83950c6cd2cbe6a6abc3961287717219ecc29966f26f20039be337f247bf61b93f8ff167d3268d2d7a5bd4d395cdc088680e185abd87a196d4df457453c3091605a4f97a636ba57cddcea92fcf921b471bbdb0e837e6854ea531f7f368a4cabf8c660e27bc7bec60f6cbb17f9bbb826c5d0b9a9dc7d5534559ab1769dbb6473f17e493285f7fa5ec4886dd9c60f65194c3ad8b8d3cd0f0fda30d40ef9da17bcfeb2a20d1d5d72452b61e993c363c575af42ff0af8169f4d3074bd70eaf852723ac573bce90b704bb52dc89599f8b0d55dcb548750c2c3b8fae08f356ca2d4e8f809a92f07695dd4e6ff691ffa9f677bca1455e558627fb5bb13955f2ed29a7d26af63bc35cd87e66bf1c63fcaa1d90351da70c748048be2c44cd887e8db6e5a0c63dc0a70cfd9680bb6ea045eece2fc3e047b34bf4cfe4e52efd2ef76c69436f1e34c8299c322a2730ed1dc4ebc0fa17e5901060ed506a03c8421e3aaf1b7085a6f004038023d4ec38b46f320696a0ce5d0abead460bf289ecd3e3533d0121640b98ed01acf5b8289cf875a890c9d7ca1baf308335738ee1311e90d411b6ec0a493e72d0eff24940625e82cab1f895900c503e32ec188405d3c9d0fa05ac490426963c93a4c078d7606387808b4b69345735aada493769abd88f62e0685fd55e48eb6a0608d652ad245da51742c16917004ad21eb1827446ed793e2c6167eab696948dd130c26bfab2bc17369c453488f755cafddbd90d27b9ab085f269d7a8da7c30bd5e4321d199f3eacfde77534956a57f95fcccc65ec930c314d90345c0b87536d778fd2868cf725a9f4dbe346874ed658906a2dca1e418243defb3d85475c7b6e6aa05077f64922f02ff95c0162495c4256cae6d73c3acfed74bf4a9451b9bbdf472c5e42744a6ed16726f4a854b7cf32d2244442a3c294986f3f38dd9d2ee1caffb8d7df79c83ef85734798d4298b8d4d28b213a17b418b19a4bb84b0183ccf934ae172a12a4b85611ee1e22b2e1e681b833a8e2f6b01ee123862af4d166bf76d3e2e2a84574a9cfd69f4560e3a32ed88e1ad8aa94079f032dec21327b1f543febf524b72ce3e46606895effe8cf66a8f5edfa808ea2c0bf6dfda9f061be7a2c65bd2504eab936a64bb993e567b3e69acb41e8db2dc0b93bb27bf079ab1771555bf19f36b907d85ecd725623e26a90916035bafd5d87525c5002f0eecf56da09818ae304b9e525b1e945c774fb145c4c8281e5c622e353264675a6cc45f2cbf363c58aa926591d42cde1f8a5be63a16e5897db3a2b49e36769d5902f57caab8ae24228117fdf868b34e53b91e5e307f58cd224433f3d7034ce4368628558c7a49e3937bf3e05ae0d3e58769806975eb2588e39bfdb468f54acac52885e4cafb178dd381f023966c7702cbabbc6b63e5ebdb18f07aa04015121833efd32d2e439efd9bafda4477203c0fc78d052a6d856c008481d58c82d3bfe90fd4dd7f0a7176fbeea1369d2dae55858829db2e9c53ba3b73c917d0cde7dd11af0ec73ecb2368cdfe4f26ccc7a120b30b76e06f40b5c9df40f032c30e4129b496304285d26fd75f43d346c592240d8e578d2603934e253323696cd56294f3b5f32cf6e4d851a01517e0e7cdbeffdd73e253745f866300e0c461e1df971e9375174804d251651fbc450450e4b3e7ecf655d0a4010c91e400359ba00c0b19f466268ffcb31a8a034b97d6c92d27da6e020ec7bdf5fc5dfa5f3da2422fef93b76a099d8410298e93aad7e11cc5a12246cb834295acaefcc6cd01bf8a46cb4c6f21e7351d72287f9d63a2424eb6974a08139e038860665a7139892d58fd19183b6f6d46c6d104626711047b52774f35f0e0c29fe725f7e4f5794f83998d988c6e940c867b7069505478a9b4ffa25f1085a61bc3643bfabe59d2950f55db89efbbf4e3b2ecfaf5c69b218828ee0ffe3f3f90f252c546f1bf3ac4ff475c89d0cd050ebe07af9219db33c599411523b1b775c7acfe72afacff083f029474c02629ede0628d7a616d2c0c60ab8663ae7e4447a6f1b8fa7193984db6a22353307813ba83ad2aa7e2954340d0df06288c5470130df9776c0a41e9b9a3f4ca5cf99eb55bc30c3f3161faefedcf414dbf6bdc3a8793adb69e83bc232df7e9ad6828a88d54fc73ae883fa8864d5ad5a6b6988faf95c20536fd94fa835256eaff781880bba41b56092ef6fb72e18305eb442d867ae2130fe82e5d09fc028bc4a3fd2c6ea2f35541e5f4cfc17a7f04f3a4ceaf270f6dfea8ee05f6c791b042daa1e24eb654c5993243c7d2e6df9629266fe2823a930844d5993c2c76b398832c2f5b83a2861b64766f6697c7104d17cf363c72010966dc931706db59bdb90dfe57f4e382561d38a586d32d1a7579f3c414fd2c744645ba1a0f07c6b4ef6447e4e4ca72537c2f98bdf3faf8dc39ea91824797175f93cfdd6d3b18c62772a39a75d58af59d5e51ce7472fe42c6eb841d4342a7cdb210b9180549437886ce9b629edd49081c2cb5ba6525d6e85776835d5de5de5fc8647bc6fa5b48c4caeaa1785995628946bf1a4ec7c84527780a83728086f97c9d681acbbf3c9c78f2a9ab600e68301f547e0bc14c54faad5eca38604880d3fc916065dd629ba45a08ffd69302cd5a822832fe48d5bb993d4a3a936515f45b8e0f2a0b44b6be14c9b80aa54c6ac49d44a6aa42734ff2e112ec3c92ada6c01a8221aa79c2f774db30ac2657de3da4dfa31dac1bba430f0b9fe3e68ec6d5ad3fb5b2b9bb1f3e7fc2cf974cd61d4bda5fc69ac092e02b35e062eaef33bbe8cb9632b030cc8c65967a8cea394786357ccff9aed6916e137c2d565c0e5afd9c8a915ed9f108c74c84a40b964263fd8df83b4ee91122c3f4f30d8b3f0db93dc8112cf0db074911846657dcca3300398eb1727a409e3096bdfc84cdc359bc2f4e0a709a0402f9539b1fbc76d33175ce3aebf1f99306675842f895f76c18936d37065b00fee699ace93ecb05e526383bb7218fcd6c16538762dffa972b7ec495b08e3ee8f633fae3b01800fbc12a8368770dbde4779d9398b58d72ce8b89533604efd3f700517deace1525e9101da59eb44c5a4af1d4321089216658f4c86db9f9a505405138dfc14634da496e784c78ad7965afb093c6d1e0ff63ac01238c30b7ca43af41f0741cfccfc193b7316353dc11d81709695e2a0423a756cfb4920f24705824b9bd7bb1b349900fb553167b5d9ae7eb5cfc3de40b58a2fdd779103967cc05ea5ea5aaedc2360fd6355bd4c3af1ce2fa0679485804768bb5a737e9906d9f0787a659f7856c671a790e8616556fa353e5394c5fd980cfd0328d5542ca67a52ff06c12c1894d8e0ea30e5f9394713be1486c813fe6fbed669953d4fa86fdd436c65e7e696116a64267217b89af07f789e34d5968067f725d65a70b451017b73f687ff0eceb83ca44b6b8947d1b6f8e3265c5b6c2902cb3852779380f6150ecabe47929dd673cf5735d66dd40b897925bc453e5ee5648a567143eb42d7bd5304b20756e30abe2c998c3922ad8e9027d002952224d6426d26c28ad4479232e06a7709b508452d72f666da86cbf5a69a18e6fecf15000b1a187020d831e765b9ed1e51750e7b1befa05c9245998ec8ec0cb74381e5ff8687fe59ae3c5ee9ce5b9df7ddc9f23555ffa998206524e35f9a648b8159c80effe085c92dc1df2c10e3d0f0abe637fd8afe6329d03262914b244bb03ce93254262c9738a98d30cdaa55475ad8d53f902104691a3f8c07fa39e83a6d9b340ec073a6cdd9b34e9451ce6dcb904f2f010ee49fdb182666f87fbcca9753ed6a8e1ef7cee4c40cc745a30ed4def35e4d73a90807d185659d2693a940efd4221fed534e9d78e5feb9796b967fac3813b44e62501a47fb749f3e7b20037be88b75c4fe5ecc8aceeec768a35253a41f45ed3cc612770113145f0f436b93fd93fa71f27b638f9d9207c1658ee5b684dc0e64b9898faac04dd8a1de918f7314d31fd7b35fd9cda892be9c4a3cbb628501ab999852c69cce90edfa7801c055959f371487844bbf4381cf65c7d8d2e81bbd5676b8d5c176b205974b1bf547d0fbabeee4c3a8e6737e4ec476e980be868e426cd84942933a50675705b6403992ff1264c0a1572e9f805d143a411a2020ce02b0aac534ac9c3ee1bd190a34e2e9355153c50a5979857ebd098f62216163829b4f40df226c9381270aeac5f18ee8d30ab59a2d6e9121ce1bc36807192a05e575613c5c90ee09234981286fe7fdb8d0afe3c775faff4d0ac5ab61629244ac2420164cbef1ff2ff05c0da2b4c79a70fe3b9906ff4fd919e1802bf81602b16323527c9016f788aa8e893c6694e99df2ca53215216fa5cdeed280741a691177dbce4c3b0a42edd71ebae432adf32bc2b6efbe59abab88a13637f87defe1bb4f848139119c5bef6f51a92074efc7379b1858b85b38652d187538a3a431ff2cb905d30880c0a75c78224d4205652d30cdb0369b01969a844f1088ed2c782b93ddd135694afeb43eb30feb716de97d2bc97052e623b301441e43017b1fb69d20cc43e0f3eca3e27356d9ee9ef053fbf5352c4accdd3802dff2f966964068b51863b9b9af198b9c539f03892780777e21ead4980a94f01642a7328a6eb71138d2b6f9652f6e8b236224db28a845b0e4d2d2b1bd99bb29cc6ebbf95c2cdd23b1fa869ec6cdbc3681b81e64b7fc4a998a14b8224e174808b7160cb7f6147afe1bca7501f8982bbfc6313a099227cace7cf95c7659047e1d6795aef3859bce455ba699b6459bb55a5f9a2922d39e918707fb8c1b7ddf6ffc13db83ec00bce73348db5d5f58d71c45543adf7f4bd401529b8f9af737895854fc8534255952691b4e8f8c48500ca6a19026702c9cdcaa618457acff712797d60fd033cf6268ac79c1a4efe813ea6eb06d28629d1291b7d9d73a8548f860dc6efb0bcc4087f3556a9b5d196ca94e4970e85cc1fbbf91a933c8fa26bb2fbc7fe01e11df42d36bafc55bfa7d3e28fece27f928c7df0319f624afa4ed9a3b27254541a5ee6796285c064fa36bc379ea84ea1f89eaedaa62425c900fa041dcef726f698f66ad492d2e27e2220900be9e5ae3e3af1f97ace17cc1818e70e8a8e2df15e5a01ddf19b8590451a10d5daf653ddd64c7ed196d1b8f3b30430e858870406607dd52ab385b6c354101dac21bfceb91c3aab1ad89ccd66f78f40561a6d272f231ef4577b824bee68e17e167865c564fce912feb2e679d7345ee7966c901c580d3f4abc84b6f829b1869a62eca74eeb65f234eaf9b4cc4f43842788280d2e2cbbb8d5ff86c30d56cce81f4bdbbcae3f01a307b1543d466bc61028ba6f0d54cecf3f1aea69e1701824c3f4155df6ad1deace6462cbc2dd4d425bb1964d507dce5e93baf94dfbf67cc379d43ef8f449cf6b9131f8f44e1a600e0b54046778526a9e23b979eee710c1f00840b9a8fb24c33dd4a0950c9e2829bdc760ff385fcd56c41b3ca6bee43ad7d5db724c38c26fa01f3b508f90a9b3be89dbf4fa4c7697add1f2f90c59abb3d7d8f0bec2ec0634538295af3f499c28b0bede000000000000000000000000000000000000000000000000000000000000000000080c131a1d23262a", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 43, - "comment": "signature that takes 21 iteration(s)", - "msg": "7a0d000000000000000000000000000000000000000000000000000000000000", - "sig": "ed23441ba35fda987b6b6d65e7bbc6723aa1e8cdef63fe0df8987a159fc4de9d201495459368449c1b45a8bb8e617d9f1530285b3001c66d371e8bfd8e758e95ce5b22189ab7befdd76350311a582dfc8e43e9d3b2b86d34ccac8161cb7661a26e7dc500efb4c229a88e55ece57f1168ef19d55a6552e7047c9baeeb0a9bade89d2861c9c1a0a20a5bd33a71301ea484674963ce43d364d841df3943e61fd29934f2bc6e7a958ceaaa0f56580cb41ea8ec02d1dbc6a807b2dced10fcb5592e83e2e865c867d946a8d9d23953db03cf263125fd109c2dca906be6848a11644aa543547f14cd5a875a3b8a0bd14484d898b9ffcdfb0bcb98c741ce1add6bc4c2977f7de88819c5ab332e72e817eb3414132988f04d1111a5fa8b88428be218b7b3f31bc3d0d5d4f97697904db1f50f1a052738a34cfde17ba12d04619c0f6fef2651178161cb5cb3ed7a615bb4e0419bee15adbc40c3c625bfd52453581e07e670ddeadd73e0e9036cd3122cd050bf48219727f501bb142891960824b1dafad4cfffaa4471d6b56e75e1606f86477529928501a80869395896d999980905184f0363feae413d6ef02ce85a84cf2f69893c53b0dce84acd299b21c85d60c04919e11757bcdeb130d147e5b976a1a19b3dc322abc2b98c1712ee1f56f7c38a9ba0443cd60accb46331b64e8953a97fc6398e70d155ab76bf69bb48034b48cbe3f26f55e63316839c6aa0f4863387bce043e021b1872074cacbca8ef71d46fca908b60b1aaba254d8d0a97189e4aa48a103d02bb6eeea2561e365862bfedd73cf9670cd2db8b8d5fe2d1ab9120af2907d80183dfb602b890be355e0fe9e979438d5eb74ec76eb117a73ee2d17303948e92aa2338602295b810ed788cfb7c940001776a3692cad5bf06bc14ccfa1c8ee260978e3272ac6051a9072b06a7808ad87a899327acfd854ce972a1f77ac374b58b600d7fa6deb4072e3ba16fc113a6424f96f474475a037a6e05285acb8a800090544bee7c296edc7ae36c29bcf66e1ac474b3a7479017e2f4ddc2fe9ea0ec229186e579d5a622dc7e68a6af2299a75f640cfbf81187335736762aa97a77d5f8863c2efc69e064db1985f2380ba341b7882894c3e43a41900351cbf9ff452156516b2440c8449a2af44478e78d6cb6fc5538d3df7b486b388a3d922db485fa5ec492c5e659faeb87ec431e492eceaacb5d94a969b9049f9fa7903f9e29d1b0cd7419e9657892f2d19aa73ca9aaf9ddd3a1599df771883193b54204d7ea300080893c0c3ca596e25ddf4efda12be896fc2c40a6e98801fe8687c7b0bac9393b5c0b352b8210b88d5881b3f43865842a99116bcc3cf781c8d5914c354262451c5f14f84cbd3f64ae659e18e6e7334f8c8a989ebc37ab72412cd310762bfb749933906a3325179cf62e6d81c0e352efe44289a7454e7ffdfba346471bda2d9506537167224b994d074d2041d70c724aafa7db81c042682b320796e951c68fef5bb4efcb2eab12417e3eb4bf6e1386498862a0bd22f31bde74f7341e448480550f62d85ac64886e5c586c8c4f7e2c5f04785ec3e7400ad5327f984751ee2145b59857ae330f01562c5b226a8fb6625bb38259295b42561903afb81390197e84e5a82d2e3e062c73b0c2accfa88ae9e64f2c7bfa85f6c0eacc2fae1af36351360e2237e03728848d5da51155a565a71ab02f0308919fb72c37834e42e1dac9975c1254320dc0d7edcffc659637832ebbb57006f7ba591f122620d5f7ed689afd21f3175e53f5e1d9e810ad047e801522de2d5b7fa463dd03bdd75e128e5e8dd58a8723a2a3ae05a84298bce323e8842016ed45ffb218a2e97c61ff3598d1a22bbc7205aed8e5e78ba70bf1b163e42c129e43e34abbfc46f6c39e339b1dcc1b65dcf36e4ee558c6ed790497ab34dc4b3bda5eaaaab261f77aeab92bd5d672ef1ee62d84c01074a29229b4f89f1d719f8319b61da7c8d5723bd738ee1a68d3e8dd94d19e5a26706d7bfa9740784fd39add2a47aaf7c3642c248fd01f8b3e0a2e4217f5f1c0fc70a218ff8593da68c71daf501cd1b38abba676535e57ff1bb84fb11a70c71efc151df8482a6d3b5dff91ca9ab45e4a1e0019d0ec03984145e2dc242d2aebb4c0ba77b3f7498b563b02a77dccd8baaef4b755f300fdce3d17f38c08850b61c01bc8e186f6f6104b1e44b3ce2afcef220537a5de6ab0c982c1dbee7d567f5e0a67caee230dd517b51d8cfbff71f8cbd35d73d800b6ce327e3d4e33a7d73c8fb4f02215c7e5afa322dc72d4618b9d48dce7f7c0b0c887eedbb6dc2ec51bd0526f4c01cafeef561699fd0ce3f10eac20a016f28c4c46c3e742dc0ef143b70f32b924064f8ea579813ee12a96d68c64dab01ec7245a2d68773069102231740b9eb4a3bbb408205112266168c9f0a11f32a45f2ec3404d3eed2ba5383fbb14efe2980df9d94b85610bf286548c7ddf6c32ded1d7de8d3600eaa63561a81fb3be53aa923d81a29e5f61710d0b0e72807912c06866f02252b7620a5370d18264ac5de4484e023f49426140b7e848ea0439ea23cf3f2beb1a7d444ec9841c3ffff99b2c4a05d4cd640b2e8a3a5d3cdaeae9d1184b3b6767761bfdd390c736ac70254b6dfb615715d9204f764a4c12eeba2286d5be501404d13863c689038094c70e4aeb010446ea6a7c176d045da5533cc717f4a7ff7c08d467dbd9db077520bf1771f68268e38f75f8a676a2e7d0aaac5997d4744f727d66a1c83ad2dd470c0c0afe479cc1b0e1beb4fa8e046caba2999d803d3c09618a60c31f221f38bce78b2b638372e8fb9d7e23cb21e95ee54bd6247b99483ed7171cfef66ba8ae42d7ac8ebe98d493fbb36536ae5b09cffeb5d0b3c01148115be47f299dd192208a62d81e9038debcb2af011701ff72229e823fd75d3628e2d0c7c8e9e21768206b5ce5aeafac50c0a67029ac4db0b208c02f47023d026b8d9c9f3b3c8278189e2dc115a8fbd6e0fa4a6e5c643c2d25e4d8854cc894fea8a992c434bef1c56af9ee0b4f1e3622a909076b1fb1400879b244de213e95d9b7038bf2663cb6cb86c6d78309e3c721c260133a6416c9df480f637654bbfabd28b4f48e973dbbe77be9279773bc795199173cd07ce1e070e114a0e981a5ff2c70356694f8259d76c88391fe2463b94c638c813596e586a8230a324199f56c38796a0e13b4d6b2a8b4e5df91dab1425c1d80628b1caa3afdb523bc97a23b63173f888ce8b0e1f4633522dd7bd85880ec564e0b0f2f6fc62c82b1ef3a3d50da8a19be43de31b756d14df6933903165c92c6eea4ba96b03ec24782c1f474e48e902b701b991f05f07d96a79457757fc6ccae8934c81160f336fc99cdca0c01fef42dc4420ce97e679d25fa304a78fc67389db7d1731ed8d1debf74e74bdf42d0989ca546aeeff653e350422224bf9cb203e945971d5e942f9960c5c40edf960f69bdb0483ba0f82f364f98fcaaf82fa0ffb5a8b8d0666e66dead4ed197d99e20c652180cfc180492e56d500f0a2d05ebab15189920b859301b33b9f17e984335466f6bbaef53b9f54edbc110faffa03a9a9fd3d9dd2ddfc5e68db9aed6e142e53e67a39aa75ccbd82acd663868c62bde5e5201e93fb82f7d6e980ce9ade1fae28bd0f7425fcfe24d5f79929216ded87ba80f71937540fbd78ee4e62044a07134513a7e8f26542470a9443335b1a3fba65806bc71af33d2f22c866ed3d37a248c6b316fb8b165cae573d4d07a10b697ed342b1955412480b437deab97a638b646ca1339fd359afefcfacf4c645896f7d6728f2299ae9985f0ffd833bd83d33d10f1f80c3ab573628ddd458d859d81e4dd5c3da53fa46076bc48fb47b3f7ad9c42c4fb0b7ccd6096c3c26115ebc42038e474b94f4d93b99243754a3756f972fa0a1776d822d7635bf37e57669057b7963bce4e6c29b1d7ffc3233b3dc4e25fd10b25480b24dd98209cc2db00f55db825aa41695cf21c150d41ac6856df07799c1a28ba1b105f58151323cee6ba0365b68e3ae972bc707b13eb3506a99551f14043e60bf696c73ac0bb314d1d2c3fd90f43590484a8a233ce96991696320885c210414716cdbb49435469f53858133356abe01ec83e338ffbf1920e03007aa2b15b5ffe23a559c8fa2fa79d1fdf0c83168e313e9d43bd4ac1a1eb23d729673f8550766f81ec839d4bf47b9f12e9eca4a60f8d5a503e72a9082a38b6e3ba397cc598e4a36e1361dc06252611361683b1c9367413044bac6984ab060d49ab2e172e84b109af1675f7ae82c71e884382fbe7d077a3d8731a556be07b4e1f13647f2f0a65fa9b0e98f25e74e382737db6b8c1b11503d6c440530e046a26a111c4b9a906255faf80cc142bb759db1b8886ad670a0c348a1e84246dd07c0380b6eaf009bfd8c157a7b090cc8b8b0e2176c788a18d7229e186392236af1c6972171e7fc592ab2b95c075d49eb99a042233deb2fac1549b24ab473b7f0b3eb39a625c77b80a47eb47b3f6682313df95e5e1c970a2059dfc82af2363825369bacf1f71e246537b7a8666730f2ddbb1e41483402b2f0816363bc65ef811964e9f0695634ef06160963f50eca35cd23a1908ab3170a342d41aba97e252ea112d5bb1f7cb58c70650a36de5dc5661a7918a50f5f65d21e3b033195e2eab792cf5faac8d1ccf907c2e5ef21b2318d6ee25d221d6ad95bba495e1bfbb6d6eea9e9d8c9fdcf779affff38f91b9753e4aca66aea1894cedafddf71d404e24efa4e4014cce1ad3dc9c9ee01a86f4ef0a68817aaf78a9e7b34255d1fe98b2c722933772949d5184ce4fec563909fc19b9d03e4834af91c97a5e29d309c2559ff2233eb8b569a91947ccf246a0d0f27dcf7beea5373622d1eae0a3d4f3217404639ea874d129db6842d25124446c1b0898d635d141929e19143b460a506618445d843b3fff0710984b53a0ede05a73211ad771dea4cab9faa3f5b00ce5a483686a0e970096b9b7e2e8447dc78dffb72fc9048bc7d3f1017e506345b8ca3c669388fcfb500ac3bee3c835a669515584b0502803b351b394b64c9bd27b57c63cfcb990c623ac0f8d8835d7a8dab30b1afabbb57f6d3194efd5759850e5adc04e3fc6bb5d2945bbf2d540bbdeaa32a38e5a04c4d04858e14e64eb298140ac9f68f626d4b824f277bd38cda238cb7adcd70b7652958525e7a294c4f5f3950f90304abc9ec081b97605f33a9642f0931f6d81781cb8bc36dd9e7aa7500b44bf83f4e14c5f6655e692690063e270e478dac9f12105fa8562dc3fe5242a93d31a0b61ba3b962aec48c3328c96e3e81c26ba68915294c190d695b4f504297f1efb8ad9e220748426dc95463147a43012638d01706d9e195a57724e3cdbef140b363c7b9092a1ce627eb22368beeb110299a0aaa4f14fb5eeeb06f278523c09e85b4323e6a133cf9bb96b2cff74249b5589aa0aedfa05032ee574ef06b5cb2721f8fe603f3773aba1a8cfa25d39984175515244bb14ba6fb143f8df3c96eeaed502c632ecbe642b4d8bcc4deef9b25f7098dd48fd1c1d23584d66ad665e9691725e775a659b3da8b0ebfafab6d3063cfc855e064e99aed544ceb102d96288c057494d78185f9c37b405d941849f1ee6e32f375051129d32956291a77a2e1b421892c94b231a37d9bdc111a160769caa18fe8d1f0fb638a75ab656306712ab61a921b787d8acd50acde7128833cfb9ca3cbea278f817c9c5c9f70e2ebcb1fb36d0b0c5c49b26f9b992c929de3af569332cb6520cadb208660bca536e214ae1b8123c76501eeb1b7cd49ee6bf03b515919f2bc452200214b0b95debce122a3b28fc50ff3e530cc55557237b069b5655181fbe986c302fe6d0e475b33e9680136c42d8c5ac9768fc1aa5b739372935c8ef82e287a46a9588879417616c0430fc206132e9f3c970d1fb61d971e80770c81938baeb937ad6b21f97f37a0e47bdbf5d2b832598c8706ba3d4dfb7e33ea34ce8d12eeb99ab2ed89908d52384ddf430a4f23cd421c28e621c8503c2a3ce27c83718ac47092005900dd7c48caddadc14f97dfd4c1a7a662c85d9186a737c677b08063322b13708908dc0230636d3025746d044bffd4d7604284a51dd73b5a3660c34c0d04ac9caef2a91f89573081348c80b87130a9b4e2d79a7b61c8349ec02769409915829d76b235f8a7a07b177fd736be37d626500f2a1feb5c4bb83b4a637d7efb0c654ff27814e71ae4c13b38ce772e76b998ba9cb4d761650b1da96b8e4d4fda2048be2d89456373061c30a70d05935ba3037b45275461179b0f2a82fd2ae5a4e05d2d5c46aca74d3bfe49447885b32c251620d95c36cb56523f3d29c2719eb617b61d11f10df8a6fd7ee4a958aa3b5baa39727a876b2c07cd65f35baaf317f4e7c90b9c3d5f0102f37447d82879bb7dced636578a7b4dde353820c364b5d68a64146608cff1721657c858a97c9d5fe3f5e6167bfdae3f3000000000000000000000000000000000000000712191b21263038", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 44, - "comment": "signature that takes 22 iteration(s)", - "msg": "db12000000000000000000000000000000000000000000000000000000000000", - "sig": "b884fa6dfaf8360463fbe531282f8d85b01b47447205a3f828333d579f16f15988bb94ddb01c99f46158a29f95194e77d909106fb700650a76cb407b40675688513b4a2f69409590806d2647dad341367ee78e2b2804d5656102e84601cc28fe75e9de7e23fbcd886ec653078aaeb0380611a4424273ea8aa38e379dac508b11911ddfeeaebb039e90fe6b27664596bdd48fd593761914a7cc9b3399f62822da5c818baad18118a8134e81ce07c9a5c0375def8200cbade11a0a39a60b0511d07b98c0f77bd8df20de309c0625cf68d701a9c30b153c5f2b9b7cb057a2dce35f0324ccd39764fb706c0c8265c3a0f711a81312b45fa129544d579c6e42e367c56ea193e2cf450f3a984e55cf289737880ea7cfd25909343cf78c1dff1c2b1fa3b8b524bd8698813528d01f2cb5f7d27424138aebe34ca4d35a02dd964bd4c548f32cbd2602a8e31858c3ebb1c297f6f6f94304e598251a48712d0e9258621c5a4fad2d905a9b945e22c5b82c514a7e01bef6396a694788f05f985644fe794af924cb7fb220cbfbb00cabb0c7d9f12445993c67be9091795f2e7de2d26f0a862bc5923ec7d2573969b4764eaf32c33f1026ff18d83112ab6e70abf3814b1da055197f5d4655a688898bec5b15c06252da28b524f55c5f7d1f04e6b1a39ac52e0412a4e569480bb908eb6f9281eae7187ba4e54b6a8988585913def1303e1cc5477667d336eb1b3ce8364ca662f8a7170fc26baf2fdebae8af43e16591ab217398589a0b32f79804dfa04645cc1c05a579709af74eaa70f19ca3a5407a950fe74fb343a7c7657c0a02b62bbcc41933e15b7f4cfa8378a59cc9dfe662b58eda58e3ec3facb24f37e41b796722c773ecac5f7177c8d80226aed7ed2bbb6443c7a5268dda337fa0257276316ebda8a762e74ec109954f7fa5a6192e35e0941706e5c3ffeeec1008d523dfb012b09aa94f903155867e2f628b73ba67b010d8bcefd410903ee38d98f6bfae0ea16dfc37b26eae08b53b616dc7ed380c8732301e3db2a12ebf88b7c8ccf42a1a26cd445e67f99b0130cb63f10199594025d7091f33a7dd6cf9cd22fb560bdacb928193fda5a54cf4c0f259f221084c899513fb6a9e18a5e0c0e4c5bec5130bcfc4a006c232b1e743c2b5dbf57502673ba4c407cbd483345e29ecc376ae18b08ed84332652588c03169b1b4f658492b87f5c8810cad27aafefc3b9e0c8d39121505bc89a202301c60651ce001d44fcc02b7ef2aa7d10b5dc4dce2677a361d79f4a83d562c1af425a44f1ab897e26ddcfbda49093e6e1e17a425907870fc33b704ef6da8e96d5fee4fc12600b3dbff955b1e3523952d7179e6609989eccfec8e45971a4535fa0fa14a44b7b7e7dfdfe3e31e88a8437d36403145989f82d1ee68e145c84d412b4fa7a5056eef9422dae42323642fea69f90ac09a3b7919d717f7c308e88fa502c8d9ef7ac14be6e5ccc6024133deb36b9f113aec8a88838547c122dfdbf387a5ce25580b982d46c71ca8c6dc6b8eb4c84215b47ea140910425d7fe0128d8fcce1618c4c6459cfba121a47f70413154d6889dda338c2beae651e0a4573ab782998bb25eb97689480bce7178abe1cb5df8ff1b99ad21c71f1a3be4328591fb3fd3c1174c9e9c9e53f8073a8b11d35c34de8b6ccc356a1ac9f48c4e588f5da8bb009b8eb6d0a88151869c45170c9391ae5af6c07803483679b5ad10849550718814a519dc262c62fcc7a9a08be8cdb8f2176b6d5ab27fee9b2e38778aa3dafd6b74d64e55166d2026d965d6e9a6a38b2d97a2f5eb7eea73bcf13a2fce7516e09277404800259f0615d913cb310e7bfbfea2e900316693a0b317a9128ebea0ea8ce6a4cda644f7df9d18bd71ebf791106d9f74ffbf9ec39a532d0d98111073764101b7739d8d18fb3facddfd7f7f4c471c39db54b4abecc34db6adb4da57cdaa2e424731c2b8e17194b87da7d6f722e24e24a23eb7413631cbc3e7108d81670dc186baba72ec8570141aa3228d04e8ffc430e71c1ba900a87cc2609da0ac100059d85c95868a3e40b527dfa12f87ee7df8365fc86cf09f85ffb4dbb803f379f030ddaab116d277a7521c79c1908963370f91a93c76dd308195188c31ba899da808f16a5a4ecd56c6dfff5c7d900259e576a5b08b5a30b3a9659599ca6836802c132080ddcb4164c13978a7c812c3a0e8595202c27e5efa64ec0937fb29c297f9518860bc35657db90a9428c89568d994ec27ffdb544f7cd051a10ae7d4708cff07112350d144c47c2a5576eb3c7d8803d8b6864be6069bfc33a1d530bae56560a0cec19a371a09a99159d513c5e8f2976281b9039174050c942150858909869fe6f4c1f3646e86957487fd5a53d6b7c78ba3d405b052eb88e3e5a2935e8b0a9b38aee87e494d4f3fc911ab34bc021982efdfb92c67dbb36ce44aaebe5fab2b6812f4dd7cdaa2964a7f92b31aaccff673640f5a3e1965f1a50694c8b86652b053fc2caa0b5d5960272ee73d1d1d56d43ebd2054bf6b4972c5674cf9df0f57144301413dfea2c0e9dbfb1f240bc6d18b72faa459b9206530f401b4f863b2a6a841e1461d40ed35e176014a17881e51df4187648815068ad17153784d549f141d0b354cfc08e6dc0414fd6d266800b456f0919389daae2ec57baf525f20e27d3d154b832695f35a89874112cf35d4f7d270b8fed5a9de07428fe4a1576e2bcd22950194aacdbe12d7ba17177597bcf4290f39d6ba75fa53b0e0c52498afc49a8bd86ff3f5ee255e16c3f949626bca0ac4024d0123693b7d1eb40a5cd1a6fe17c58ae5c2aadf6be973eeef929d97b2134c8427a6faf74016a88f82a0122975f0af6c23364ebdbb37039e726f08a4fa437d861fd305c079babce1439518079a25eee3d20d1049177c224b67a07e4db93fc5ef5950393a44164c65ae8cdd9715f3d1e06dbf1ad90b3446250549267df8685399c50733b937839a9b4aac1f11c90e86a01870aafff52ae334913b4e7c1221348fb174884df279730b2f686ccac5cbb97be34d7a7c0e8e74d439944cdde0b60cefddf18135d8ce431e4fc79278677a7ad9f470217b2816f5dff9b57d2c4c9d7e71be72636c62fdab0e1f09a2e7db7d10966d941ca8b347b04fa2ed9fccd7b5f6c0b21cf6cdcc55be5e5d6072e9cbc36b14081974d9221b77f4079e3a97a801bed90bd650a302e3e24772cfddbc8ee013488d7d3610018030d3ce11209e70227b031ca282b94eebcc84010a1699429a4b5fc66cee0cfae8a88dfc16dadd0b570d71156d0d73d2b636e084245c141c3a451e91e0e46ee6be0af8e2b3b79314bdf9c8f8f4fe7fea228ba43036e00cbbe72ce455018f35b0585255cfd303abd2dcb0a757bb31923e23550110e5fd125fd4809484dbe5c3465d2d55de80aca3cc6a1f078ef8d3e76acdcb381fce5925982b88f98641c5ae1f45d2dd72b457b550e8068cb9a8c9ebb60c7bf21d08896514433a245702da5d7945b7b90c9f2872241937e4b84b2e182c52c8834d59bd763bde2a803b3d577ce0d3971e73df57ee3f116389486355f41f6671916011697c8d2bfad6746856998b6539031fa8ca434926d42c2c10855d08639b7ddaabef506d0d58a9cde623a035c034cb0ed24c35456b47e84cd57c7d4ad2f44d0db175c79ba9fa1479dc76c633ab1e10cc58b51f7d47c82b4ff80a1584473227276cbaf6baf4f65ba33699bd50da0e5488ddea86d077c8811f63e957b131addd9568732998dd9019eec9c85c633728d18e687f1f6f81d5cce1e4419d0a0248b5e71f566be6928bd990d2835dd22f52598920759b79fb4c073fb2a25c7ece9826afd572267d487718eb4db8b56b87d52dcd723a45a2e378278124fcc23c495337c957ccddb1e336760a2cea2e04a82fac1b4a3910e8aaf5c43f86468e51f36a494e4130bcd1842cd654666e47467799f5e39afd4a2cafc0a17b6e145389a887784bcadebb0f2850c1f7df4fb9b5e305887e2f084bfad8878aec4caac5e2174e0b0f2a65aead299f8174381a1977d08e82824ad2964277f9a9347628ae2173ec592b01a7eec1cb41b66e572c8e8d6d54ec7436142ea0dd05f0f6c76f754a4fb774caa9cf7f73eed249cc4845199dc7d4869e7194b4471209eea89abe5f43523d0602b6672135d961d13fa42388ab706d0ced26ca79f2e1ffdade94746a43cba40f53023edbd91c2a775054eced4bbc89efcd71cc2599fe4816701d74f7495aba9d27391b8ff4eb3eed8c28140231fe97b64f008b06b03dc7e778719f112185467ba417216dc4e96cd0f3b77ce1bb619495a595725981be971a8b6e971427277e7fa506eea21409939361e33b3873f31f7421739457e1dc8165a23666699228260a1dac7c12e441686055d33e23a46f5fc200b280d091cecbefce64864f2414e221c91e26698a91f32db3d4f2982b1d14a9bcf5aa5b0cf5c23caaa9c39dace96370b2371513886af71dd0de3eca8b769140e11967d13cffbee749c374be969bb5ce9e723da160a42a5ee810b70089953390c9fd530105b02d28deae879c37e9c4524dc34c346de714b3032bb6b8ababcaa21d0f020162802d3bc500ba5f6f43e15fd769a1520cebd796cd126390c25f82bfd90955958401d47859984b505c016318f531d037988cad6d47149428e0782c29e2bfac934736cb927d27f8b503fb5ff0d489097ee2c2062f047fa3c78173651a6f418c8f0da4c92c4a4eb26a119b64c2079c224b334ab76025044fef500669c03741da0f794967f20b5400a3e02635e53dcb3dfbf509eb7800763d02dd3ded32d52dc3352c1d00bef61df1f07d1fbd8e3b853209bf66b967fed9a9f828c04e95a5fa464740a46c3a1c6bcf0f3fab77da15cbac400a2aa7430b8b8e5584eb661411a8d3403ebd40f7af4077a8ab3dcf756b9149baa0ff3ac455ac1bcbf6de8de845d7090e59ba06018511c3a41ea4091549ec8212655a359999db6dfc4eb2ecb24eef39cdc4fbbf9e995a9950043306426d1fee6c8b15607dd7b4a27e0967cfef49902e758e2296ed29f102d8aaf6d8311a7f9a60ee66f971bcc63d6f0ee251bc7099ad24887066adcf96d6bcdca985443e64e7e3e56b98508b22c542fb891ea3f6c336757e7d270a5d435819f56d16fea4578c816b027417b22ff08691c28f9ce8e4626de78bc618f5df164ea79d45566f1f4aa9f061f65d103b8963ccdaae1edca988594deff272d41c2cbe5c971374a5e7e664eb55f130b870a9820246fd2aa4dc77a97035653f5e3147765fe59b7784fb22a6170cc470556891dd7c3c91a438c47b8938d3160083d85f2fa93e306fb3c135f6572f8dddafbf1be46a8f561554e47bc9b9293134c57d993ff9aeb39b2ae84262b9fb584aafbe9fb2db113b76ea74a664a21bc3ff3d869fd267399a5c7d54054264efc9c5c0e0c855df932b73bbc245c3fecd2bb3e792cd42d544eebc2150b9d707b6c26ab84d4a6c66b492802c0269622af9191cc23c9d2191c0050b2795f22ff57c1989fc3f280b692722bf553672b79d8ed906fc1be81ec9f021f9e1829bd998583def1770b6cd522d23b69a5379e1dbab91197dc24194c955ad9626fb438805ea1d3eae32b9168c8296af6d0b3c70fc23e8c0777f1664d825f33a77dfa4f11bd058516351ce6b15c654d3a5a793fd5d0299ed57436a80545d1b7fb512c3580be67ac400ed18157ff8dcad08bae6de6dbe2849673e581f5bf7ef13a9dae88428c686877cf1b00539d5141edb7f57496941a2a4e472977a946f79444e7a87a6dc2eef2054e2068d812fc11cc47078b8e0bb318cb2edd4a16b4a4a4e635f0c09351fcac4cb79ade050267a1d156c04bc706aba78b0577b3fa7bc322178adb543488eca89011e5116f23c3dc516eee7a83502b8564bbc2c70d732f320834cb31aa8d31ad647ba0414a9f6d7b12b250ab3a36a94796e47bae0870f3386af946bc2e5d081029601d8119f30e134f15e2accdfa49bd6e2c2ee0aee69ec60acacf02626a2efe3dafba47700751051efbb33d709571df8f8780405cf01ccb3485dbfbe03d438945839ae2c27715f5403224d9ba2e15e382d9831246c57e983706ba806f5f81d7f6bca73637b92d3c7e93d4aec876f4b86c29c882b1e1a562a52dca36bd42e84002531e539405a9cf740d9ae19749f388edbb10a6069c00c18366d957f635e361b6b37568bb06feab8c22be1b91d260a1cf1c8995c35eb8afc003e3d7cd01fdb4e1436d06b054a2830e14c582d88bb5376a92a179fd53de9b2b0bb64673052420edaeb9aa942629187d2e8299583783944e5532387be53f14d45efb3f0b26fbeaffbbf9114550c087180ffb756dbde8b50b02a3f6771daf981a3b205380864d422b91a98943407f63651c1fc70f431bb27cb7f1f421b4f579fafef140a4b50606f767d828789d1e84660777dafb80d798ce4132e363b4256575a6388b3d5ee788abbceef3c498b8f990000000000000000000000000000000000000000000000060713191d2a2f34", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 45, - "comment": "signature that takes 23 iteration(s)", - "msg": "ee09000000000000000000000000000000000000000000000000000000000000", - "sig": "6bde2911a41a57b744f56a0455ff08f4617301a775b2befeaa8b7df41134c79a7470ff1e7b8fa8e179508d0fdbc5cd36f160b9b2714007e0c319e54ddee4559f63e9a586192b8d5db0128f5d260fb80e7bac4ba829247662b4d572e1c7ce0809dbcb469a5c17179aa22c58abe7074885db2bed2fbb218bab7912c094cc279b7f3589e6cfc7ef6f219e091700d0e2837f7d9e5cadda8b43a91e9f18f0a9e37b5f1dbcb90b79757e25d692fdaef726f5a93f93ebcaa394aaeaf2f925f96a75152ba609952c3b8510579ddb80fe1105dd90a492a6f016c8e8dd2e8f5de61a3132b08cc9e4e904ec1b6dd98c05965de61d19ada40f9a0a1b40a6dc70cfa71561fa9e8785544345facd9b29ae411f3233d4c13a1ddb6047d96c4836c9fa06a84bcb690ebd2ed9cd21f4cff1d2822e15bf840f18d041d5739e854bf1972bf030b05d4f8595bce55cebc07ce271b97f7cf53704af79dc2c6f9656e6fbeae884d2dbd15d3ca4d547c612207671aff2c656f0f19a1e6060dc7a26bf24ac17bca4be0bfc655f7d8a949ce9ad1c8b72a7255fb65292988e37e03819957a2ebcbb22716c3f1395ad782ea8b478db94b94b0a2d66057147748e0f2ec10678962cc7628f1370575df1c59cced8c38221f1d4ffdc0366e3dd3e9ec258d5bdcc05d0284b4458080d457694d4b65c23d9edca8a6210b8cb57ca371f5f3b6ac7a9a2f30bb484e7047f172ea939494cd118ec52bd253ef41f8fd3918fdbb423417e9b962a497e438ba09d1ccd4e0d6b4d199741f9cab5026e2d6c712d6b567a4cb57ccb62145272e6c53f83bdf796dc5801f0bbe613a0be15205eab84cb5c0b7ffdb195581bb381bd82e55f770d90b202d564d404776c174d939a734618dd748f1b19bfc6c77e41c19cdc428d7993ce428e5f4280dfd0d1a74713d4f4f8b91ff85f7633f3e6d35e89f5e430df1bb8a4d3ae5a0b32781410598656469f15a9aa282d51f7984497037b8e7b12b6dec29aa6746a387822bc0e4f54d61dadbdbdbb0dd630ada12cf9304d91765c16d4693b20dbab0d58bbe7ebb1e4da2852d73d3c6ed8d4b14ad1f468970ed8b244f89c323b2279b5fde39af1c84f88d41df1fac530b073af521f627410364e010c2d76a297cffe1e1310b21f3e856eececfa61b020abc3c78d1b1604f4d8b4140a095f514329d445aea02bf4b221e15943f4d9165fbdfbf6657aac5d6224259c3b7412352e5a2661be046b95f7f0ce15ea2990aeb8a4c56645171ea13fe93990d640187ccc68fea84c2559418e292de96e94e413ed827b47e88d216f5be2617024d18c7584dbe2b344027fc82ab66849e30cd5138c4dcbd74ca946f5cfaa7cb2f86381999c7a8ff45273f525a73dd0cc5e631c8ae46ee8ad6e194488b307f16826f91ccce6295b42f4435b0a5768fa3c75a238b4d2ee60c799e623f4f3bd3b3dd9288617e56d1f528db50cef3d7c4661eecbaeab8c99732efb20e26a45edc937061b919ae59e2cd94d6a176e174c9ca386393858cd76201e93ce3311722603d8bc6ee141d79faefa2ee985bc2c78ea9780c6a922e7599f5a7d553565ab07de8c3f32c3f2db1bd8b6e518ee2412b8c82cf60be04abb25f0d781ee4d3274784eb2b6e591eea96661ce399a7599b13c8f53dcf07a648a7e1b1b0525de818b3425c360a6d3fc3f526a4c3e373ae264f59a6e9f66a118350722c2c75db03815c08c37cedbd7bb75c00487c252e480f9b32ac1d3774e03bf13216972bbc492b4f032fc5dd3355aa199a50fe37ff2590dec785244256e121a426d97e4d792151f3ffb3d6a6edc4b965660f4bb88789aa91dd429d90ebe27d659490a1dd6258a3096c039a1935ffbe266640971a59d4a718c479a3ee88ac695b387b4595a29ac0261d8d6e8da23f5ad534d948884821178ea6a88ca7cf0f9321c95c28404c571dc3042a7024503768db4644f8e38ea68701b755f5444e31a8d51212ed069d75f5634c7804a9cdc93111dc66e9550e173089bce541b6870b096ee63d6d9a3a9abcc98d2190f4d710d9fe066a31473550902e7fbdd77735f40d4564f6e6da52bc01fae86b1584f4a2888b1cf24ae5ff46291e23f91354b4ca0a1a72c9cd8d6bba558c216f7ad0e44de9a62b85a09648af36da5e2269754beaf281f924348f7e55d682c1b2e58e8749572846ec4862ca017c6ad111d939018a4b6ea5d2ffbf4d5eb05efa50dc584add9c2136376b8eb52f36d4798123c3e678c3961af14fb295214194840e3dd0f0171fd1f6f40e002f4ee3d75d95041cad2b68b5cf05ca84a3c4d8f5b3a8065bfa16881508708e00a811c4eb6cc9b13f697c3ccdd0b46a48f7f64507a5eb75e1df08971ea6dc66b29eb0ffd02b5b2768ddee8c89b9d2e4112e8c6ccb3d8a635388984e7fd920776495000c5093ae3743a50deca4c8d39cbdd80ee5ea03ca7752a0f381d787ff273ea5036229ae45630697848fb8ddaf672dbfb3f601ba9db022c36726dcc24e87c19de455a36076d6c3ba1d067339db50aebe925270efd5d8329e6db8c61eaacbd8579761cd1591e37dc1bb7f45e9deaa0690830e37efc29cf5966a479e6e8ad64d771edef29844b46ec60927bd56b3918af11552a30eeab9292753cb70ce1ca4e12b4d1c2c93893b912b84ed0a206a3d93e1822d1797a8e3d25939583d875249db8a3cce36e25035087e06449f9a7c6eec5423add65e1db0095251186450cca90f4f63f025fb68878bdd287c7c854df597f5421006dae40f1ceccfcd2b9f85a0c882c5d455977e7e2e6fda4716bb39ea9a3609ee5c82539afe0a1b2a434f233ffe2c14d22c2cdef12db003e61f89e22aafd343a52c6a090ff50cf8d53d80a8f9311266dcba42fa06d2018b90644c39aa294cc50da9d33a49eb9f6f08dac7ea7e4f2d75971dbb607b47e8aeb1d3850ef12112dfbdbae46126aa095bf3df82082be5a674885833299b35408a48c76ec0f62103ca54bf811d57f731e1149a28d64b0a2553bd465f822200b674574923ecefc2013c11288b8bba2417e4696bfcbfd77e6aae4b1d75d6568c9404faac8f47d0601092f61ff6c72a09bc27f798452f8ab41d6549b83eea1f92a08d99bc24b8e6de13d31741401e6bc98deb6f7e96e9956820c2e48a39037e43ed71bc3adbf52993529c5b1a38af7abb3104deddc72b7f64143ebb76d911903662e93be412ba7674df52785aae31bd5d20d9bc073db87f0da8458f16ef69448bce649c3acc4fcc8e89126c15cee99020e406dfce8519183b226d34536686ed90902207ec3db73b84c01852ddd6687b42a6e039d9da58dacdffcd2f02c6ce36e5e23a4868d30796b78816622b12a300c66d46c0594807b977a1ce972019ed1168ca6c398d479cd656ef316626f2b952bc9e894aa4bc97fd7b0d2bb6bee1d39d9360b396e9c1f9ec3b4df7e0f77674e55e13e96a93d9de711a7e957a567d0ed9557da9aa6bdcd85ba723d846b64786ef73990c49abe13fe41b6b93037d8da05875378e66e596b7facc5d33b872920d13011c1a82703f976e32e57299353c004477d404c028513d0013644bebd9ba5cd8232fb4b32efac87cf3278159dd55af5d96523f568322b731252cb19f6b910b2a27fd551c735baae17e74565e37ba24e0e195c1fc4f0923ef942684f4e807d443d2d813de7e4b0aee9ee78ec34f5779b38bc54a6dd0409495307bf93b6ec066ab8027589428dce991fc7346cd12db9b14e6fc7ad81bc32e579ecd2f16b9f37f4c1105fe2c72befeacb7156c1fe8572b47aefd2d78ca7f6291f87680533f52e11b74c65376fbb3ef5be5d038f64427116242ca5c9dc3a82d996606e522156358d03cf6d1ef02206e59fca8ba74c9057b56349b89d2be5632205293521af25f0ad0849a7deedd4706447a46551ce9e18d0a2f4ed462739f10619b94cbb21947db8d1b9e4bbb1ad2bf3a4623e873a632f33165fe5cb1dcbee93c8ddbfbf8b8acfd1306426d46846a87a22975731ec79cd69954deaf1c947c90ccf647feab52ed46ccbb6ddf4f1c4ee16e8ba8e7e77e2e0b31f3e692ee72404ad59a94652b237da1ad86f0fe6ce8e9240d58f0d158560b0177e0f5bc891ca18358de3486d762ebf66ff0f0f7fd96e5ff2dcbd40ff6861e8611f1e11c4cb1d8e56f04e64c35e74e33e1e8a278536dd81ec22ef453f76c23df1721759339c8c83c0da44e580ee50170a10303b3a88e99b89aa1a8036e4637614d8f5eb0b62974063e97d105968e8d49d52a42acdc38012298170e3845f85ea36297368859df6f2e47596bd8cfb4da805608052233bca5172692ecde33709d655ed1dad7bf0f4f28b5b64015fc5f4e72218966d798e5acf6b63a95ecad8a2a1092773a6ed68f742c4965e7b47c4d6af81d9fc0e0f7398830618c381582604558852e4349017d75d22a21f5a1a7e181ba51e67d3d3bc059c33fff9468e1079bbe590b01876108c6dd1ec0a2add2ec274da832a67624a7c4570590f3cd77bdca90159ea241390a41989b8db9ced71a58f2df53f87bc6498cf102f0e843af684e63d4aea024e8ae815fd34601633e90e549eba5c3921cf69aa4fefd40e46fc3a66e1ea28fae62bdc32b4f4313d4be64c1a41b3adb5ed98e5d55a01b3a3d4671df6a00ed990957f558ba212cbd073ecec0225096c8fd579167ad9591907650d06b6ef21f2fff32ec286bba01c099ed462c803c1127b250cf0cbf56326f92e86d939e40e311b8d44434ca6de42fb0cc807717a56f9e9faaaca230d380c82f2a262e5def4a7cebef7f6cbd64e4b67c89c9a5bcf23aa543db9a7ec11ce629cb22f7fedc8dbece9c9a7e58c757e1a4e8157fc0283025bf2bfbf185516d3c1ba239a9415dd24103b0a0b8c0f71044312de7f943e5283e04698d447ebba81a41a1c729825c3eb7f03687ab043a62c535b8a12cd8d9c2876402675eacd71719f45f3beb0f5677a44178a8c86faf0197b29c0f628c45397c0fe0d9d9d1f254011b5484e2ff3452cccdc8199922b36db2d24a89a6215605b3b28ee6ef80ece5d7935efc5d137ee94e809acbe24def5952d874c0ce5edcacdd3854ded9e86158089a302565858d1fa06f682f8646a17edee4e5258274ab07cfdaa56a7a6435b9b6bb91eda90cb438a78b67b36d6d7e629b78a1296354674921f0829aa15bb04d13d5bcd4abfcfef1066d2a8661ee4004127f209290ea884c790a105f8656d54278c1af707475634c368aa1ffac68693bf21cf4f166cff09b7e15f636a9100d6922fe601f1bd766d7118175c782b7b9ec31f5f2b9f43dda02aec5a8792d980ff265ca7e27f4b764079213fb4d5bc7b3efb827f63b08e22cfa80c78a5e6f3e303c336c1d390cffc199913342b8eadd3748bd8b39a65c7d90a7b3a6273676fb5cf90bfa4b6404635842a4a3f88c12e0dd8f4682c9ab7efdc5bbfcc112a3d600229f22f58de073c1c9c49e7e0c1b3abe9db1f5284e85c3fbecb666627c2cd43392a73d76cbed093367002aa0e939e225f830c3bb65133e46373628ae61f7bc551f115c9ae680edc0b9ef7ca057fda9a63dc58de1ed9f88c5491028970bc7bef783ef260063aa68d9e53962c41f99aea6dbfa5541b5d184023223a1fccef46ab62f915463a75e4799196eae3fdad76169367380cb4785026b4527953067c5bb9a59f710fceb22be664cf01bb1be8df3ee75b4a462b36be49921c68cdbf4db7d1da891826005250f78da2831735679d11c3e74702f28f91e79f88308273fbb3fa5743ab891e80ed8825ff283c45b31437bc171a5a719a35c2eab6f3b00c498d743bbc893d87a5a79662363ffc42b4a49567ee16daff5ae9e48d9d88d48e2aca84870afcb65b121eba02d63f2ad082064f2a67216a2bb51d12ad71e438a326a8a415d3b29dec58bf01f7a1724791611ee58366e61ca94865c49efdd74724483ddeef1b60992112b821562861ba958fe2b1f2224b39eb2160d47ccadee7cff5aafc82863732578a479044c552625a9d2ddcc13b21feff6fe2608a96644c234d6101ca0295a1dbecc44112dd61651fb547e05a3e2ab98caf4b2239ee08635115d0bd8ba9ad43a2453afbff7a88e33c3ac3cf557bfbfe2339a05bc787ec54aee85bcfd8ea31061b9a4641f061584b2d62d5d5ee67deccd96ddce6c0ceed3a6dae3bb243ab8cce79bcb21d1544b991b2aa67d75a18de15653192ffe2a98c38123b18ab2d5eeb467feb7253cc6a09fe30903918eacacee6e8dd1130d97b8acbc98f3addca131e7d072197d981cad46713641001418b23b9eca3c2be8ff5f1ff496ecab9738ac31abe1a47e4066de413f6f81b4d2817b7165d9d65ab5f6495e60f5db20a8b45db91f8b15169cad33f6ce9b57a9fca9ac2e20ef55fb978a3225f777d4153a5e7202d4df87e235c91862e669acafc2259741841f6034f092f818eacb2294797c52537576c7aecf2fd070f1e4052727c8fa6bdd1dae6ec263b3e4a72ebf500252d3d4748565a97fa010a303a595a616487bbe1e50d161a21285076c4000000000000060a122027313d45", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 46, - "comment": "signature that takes 24 iteration(s)", - "msg": "1c0b000000000000000000000000000000000000000000000000000000000000", - "sig": "b65f2754a1fba0f868080093cd664cb19628c2612537059c3b6655564869349464937b52ec5434edf31dec44eea9c82a1b7b5192bc8c1407fbd6f23c26a8aabd23eefad2b10a3bb5f6843b4a399990ece310b2a559b431c39cc10f7be566063c26ceb0627ac48e98f4fd8ae9b211163ddafb7483f63de41443a9968513e42932091c534440fac6b3a1cb56642430e4bf9e1495c2b4e9986f57a3422c59d8d14cbade24cb32a85a17b1ffc2a680754ff4deaa81c4c5e6a67cc936aa5a5f1deb6e3182493d84bbe25daab91d7639c24f9180b43e543dcfd968fff2b42bb97bdc6e9886b0f2bfaa11e65ddc0fbce0444837eec482c756da8bf6d5924b59c3a2ae72e771bb39742dafd68e9a73e1be3d168b976f81af17770a81b20e2f5c74e4b1bc871e9f0a88a8073f0ae754f1904e818c24f21be0db5d3e3e22addd08f7fac548c85589b33cfaab5a3b12a5619c6eba14632af9cad739a9a173296f74ec349210a748b108dcd08008447d80abb56d686f46ce5258c7a35012d6ade008d667ca91ccfabea0d06d96e74c45294d4013a53cdfb6e059c4e91f1bcfcb65d7c3a633594492c6faaf1aed335b99cd9cba254781e08840d83dedc9897596446432986b8f051bda1b3949985600e2573a1100dbc86f91b0a77a3bc0c22ad6f237ba91d80ff66cec8c8eb1942c3b1c07351a6bc08fa74fa02185304be0d8e5d91d181af02c7910b0538353c4825cc2adddaaa702525846ced36bf532280445b6cd5932fc678477ce08f9b0fdec607490bdd91775484f18896c0f259ba231a6fb1fee9071525595b5e5a729a4b341690cf2be020e7e082c5ae9ff7831339bf12faae3aea9b12acb0b40c273382b4601a586ff778d5b8c6c865045053ab0bc95da3c9d722fb32910ccd1219023c8f30936aa0df8b134e05d3e9b26aaea6a5b7bd728e87e6472d8a6ff42a05806e0a5b0c400e55646afb81d0143caaa8a8ee4773f99c83d738908aa064db7f8cbcf33c61812c3690e36bb15aff524ff86f0e0e8e3067a13e1f226464039f8361287600d92307c9374c0a8a0276cc34e9d4e38faab060f5706b25914f07f9e769323f0fbee5a085abb8a02985a1b51bedf66c383eb095bf9112c0534fe2a473c5c166e083765b95c1e502f4c090ffe12cc375211602be1ee6a1db18474b9fa5ae4ec2dc0890170c1d94278f776a8307e651c57f13e6f7777218afacf7a1e6b04f599e2cd48518f311ae6c594aa8467f839c0c5ba9a93e940fe1fb2f3639a5b826ad2a876a21489f4d9ef408cea4c90cd6a86b71373106903dff5935f11abc7dbe25710364c34e94f3b92263224d45c70ce9a5c814801021eb8ddf1bb1b8dd6c721b75638eaf20c18f59aefbc8acaf1aaaf4685084395ce649cb39061db7a9f5376f1daa1deb5410c3d5225ce0e9be85c073950c075e6b0cd4dee5121a60d23341fd8f25d3a56eb08dda3a355226ae66cf0197bf7d046eac9d985f413fd7245a208d32e71f38a4d1e3cad73db4406a0c79189220d3e1ab83a07846259bbc1e5f7af45c6fca5f516324c55fd050d0264c5cf44a364aaa0b697940c0bfcc8550115417501d841f771f2f52d98e474e7fbdc2d90e587a7a40ad32e9a931136134e3f1c3fe16a5e91795ce9d5b655e23e81e223ffc05c35d590f4d8a594d3ddd52856d4227c04bf55b226f6a98df229f55f901ba41f61dd34f711bdfd60c74a6edf06ceb3d833b813cbf371f34b0921a39dc7e15a96525cc9aba5f46e2193ccc156aa75bb3a35180ab73c61777cff66ac4cc7f25453c58fe52ea96511439ab4c5c6265a5cfc9aa3bfb13c4fc33642f4eae6c6282fcb0e5e70a387961163dffc7b9695adedf5fc429d3858c17475755725c7c2f0a75e61aa28fd2711482835f16b3f977e7cd4160142d5ba323cdf58f7aad4727f36acad2bba73adaffb7f0a8359f62d757dc8adb2d0429a717781bfa456382a7ea2a7c49fda61e8989feb0dd23dba75d39565645cb3eabd49fef19d3f9d593c377afe73632994fabfd667c6bf4de0e4e5bd40d9f38cd7ef7a047e051324e24d30018c2f83b17c0fc5084c9610151b6017bb0ea1cf1f5607a8c44c5d708b6f8bb8091ce1b8fc751726df60f2ce4901adb873983941934ad6106225040839e4d9fb21a3cf1f8f4c66a990d8177097299615ddd27160e607fbcb4351b5b99ab687a522944b71ac8e11db930c1734322968d984cfe94c62b5683c18ac5a7aaaca8b282bdf9339182831cf768dd29897f314b21e3d1b2cdc341b261e4fa0f3f135c7a47a22b7d8b231590be62ba04ca3d2465051787b78818244d8342204685b9a23c127cbeda18b59e60046441451a53df5fe9138eae87bab5051f4242213e5e2c6052889876a7e7d09732640b87c09b7905fb9841a1631a80560a5ff6a5793d0a47e4254d02d26db42e03d1954ee6598bf83751bffed3a25d7ef2d147a93ea400e81d0c9a6499c21f025489f104fe2781195af1d57b81f6b4cfea585e316249339e08500558c5523760746d582e09ea7eda00dbee25d0dc82ad47587ab8999b7c31a1a25d1f2988894a2f8649017c8f8e431a0ce939028312675449f90c8a61346f41f187a30c7f9f4005650b7e1483c6536c065315a249ee921e0afee94228a2e4e5d3fb797a0df3952c411dc5ac0ea79b61b598c99662f37a4cadbbda8f2ba2bc754e67f20efaf9e2e8b2ab023f7c022b0b7c45fabca93c454276e4e8a4a9d325ae5e5fc41638759bd16fd4d5d28fe9646fc0e45675cdd39f9e94478804c7bb20cee2c38b33fb3ff5f592063fbd0ba2777cd6f5760e5539682d292dc2251c47b576725a27cba7c04f457ea7f2e3bcad9f7c64ee14c3c311970513b6e79cbbafe696adf9799f6aebd0e56e878e0847efaa06eaeb9aa1fe5e1fc95da06bc77f29ecb63d0f6eb756e763d01e7c033a87d78979e48c46cd2634dde8fc601c185400fafe0b97bdc3ce7c852150a830baa0eff868b9ad5ffcad14094672735dde81e66e5e4d8c14f899a3dd9a286ccf3f895f3d6eab9cf5b1656c4605d2eecab42df3e80e4650c0b593673e55f8e0b5ea1f76fcf04610beae53bea3d21d4bd997a5eceb7d5d89643cdd25a2d1adad4bcae9183431d002d5b9744c786d61ee94a84f5388f1e541baa6313286278603ba7c3f8b3e8aab5139e1ba734d2c9fe4aca82c84a2a4d71fc69952c34eab64af9660ea1c2271d2ca078c3b14c0f7fe57e8556ab2971c253c47874e1367d2d03ee64ef1c2c8aef312437fca928f4628a7338e50dfc723c054c6481f129f3d2c3cdc29eea9b1ce10652051ab0321e53f8f4876a0e262d13c431c4235b2c9f2b96de6cbe92d378db823c6459cc97106f261d0b95732de289c4650ee6be4f36283cae19d000e40316c5122045b6b458b739006e88427ce3c9b2fe34533815438c7b89b6dd266d8affa3745f8bf255d6567eefab33be826284022f14688ad59ff4fc9b3efc41d8f4914b35792d558e64a91311714c3291b5291052c9e60c3a572b5f21abac1e2e96923046b14cdfbdd40ace2ebc2ab78ce06f97ad974eb4a49b0b65c192f45f64e5ddfb954904cbf312fb243103c21698618c4044ac6ce949d9206cceaa5ac2bc813223ba5ebf6695a4096e29e5862bc059b52fa9d9af29be6acbad800a3ea72987561acdf13466a0effe64e2b7ca8872bc9f4e15dc9d2ad2dea6b85883b1137ad277fff2252222c7553a70dcb5fe0fa6552d5a2ef3af4495a699ac4520d465b5b1905072191c29f4f4625cbb0f197c5f942d7abd4c625b9849dd127052ec839e6d42fb78349f42c4517b402679abbabc1cb2943c1045dbe5c2b7516f3c386a93597a1d12578810bb4cde96a932930c1bf6c00b0aca050286f5a8ec60103a191793eec84ec0c2e6252c988b2605c545aee34c918dee46e963ff8fac11682950f4693d0809cbb695b0641daa9b203e19db8468528b2bf59d9e135cc63d745699fcae877960ef8c5942539ecd12a2116c868a227034e0e1fd50c43540fa43daa487f95f339129b998ee385a1b3c69316e25923fdc8744199b1a1bccd6fe8f2a32acc13156ef9f87c67862964bc297acf907b1fa101af8dea93e17c358b8a8aa3161fd325364e915f37d2626a027a13bf46fce35c2d341c9ccb49ca87eec71ebc170c38ea63d50f234a1546e9a7ecf088e0994e2199bf24c3d4cb088a7a28933ce39e5ff4a2981608807d3802749b8783bdf7e241fad839d83a11866c27ab70e24d2e76414111180cb9e15461b47e0733eb6f640d3fcfddd13a6018c1a06fdbfdd69da657c7096e239176d1d78f1ba89f5c413f282f662ae65f10f177399eea51fb2459336a6628e5e88e8c86cd82cb60ea59299a5b1686f8cff87ee155adbb7576617468ad067c8d6bd68ed151b77e3e465fa92861410686ec7489ab9c55adc6b1d5ff3f2c671ce2cf81c2086a5db36dd47c86a325a79fdcba07d91d405571805ba07d1ec485e7d20777db758a38992deac6a850a9bc8627b13e17ac137ed5a59d901dfd7de23ed1599884f977dfd07554caa058cbaa5c86d9ac2230411596a96cdb72de7e5e5ec81ed82809fad19e1ae9905981ed8bb9b13337adeae9c9aa83acd3924d1fc9390d0f904e7e8debcf934a9bed488345e8e398c5eb75770c6b7b77b63d4dbfe83e62786bb65a752a9aa42c601d1820dd2c071b528cbad1b23810fbb345c440e7e0ca0167a89573d6270b06db254895de08a954c1c0fa5d20dfd8f820901329416ed669ff6684733e19c6a4adb5b0749c0e714608f9ffdd53114a6d49ffa316280bd73f48f664ae440a545e50ddb30845d58831e8686df9d23407b2dfaf21f418abc88eff48f8e753f6de0769f3b183b6887724989cb52276b157e825091b0a9c045ea26759269547f3ededa069774561adb0efd801b763c6c89702c106fdc3bbe2f79fe7a4389f079d1f58f6bde7d3d2e5c7e838001b5ec2ae91fc67ab06ddcb7eef017f1a9519c9d24db2e7c447dfd60bf1fa1e9c2bbffa88285bc294a384d46b911f3a9c0e08047a3a9354e78d03758718a36fae2be0828248928eb5a7ad32ab5ba308a3544586b948939ed130d4852872865558df491aac8c3c0c2c66c590464910d962eaf935dedb4f11cf14861f52a5a3296e089e7beb4ae37749e68a443a41bbe17c9b42dfabbf173678991706937448a3b6661eedb8899227dc65ccdfa3befc81676c5a7bb3d9edd7bba71cce703c2a875b200b0b8baabb7da0b6b9604651405cf0a832f76789f9adc965b1fd677047a89e502eae5dd90c902d8a9388bb70986da1050f0ac4cc6334c0b37a05ad4306023c8cbb93263cdb4c7e6cc289918479aadbc623ee741395b8436c3d37230f3ef230d0842b362e8ac49d9ecd094bd2d5127e24bef8ca3d295bd12859cacf6952a7be495f8ed8605c38b0fd4322ca0b88f5de90253b66f1c18b0003edb6ffa2e3a597eb65db7df72abde9a6800995a20d9918bf6d49aa8a1579cf9cc42a4aca229eff09445f199b95dbbf9bf78b529f4fe8fc06f50f024cb0a2bf6d24675f9480d2358d676b4a8fa49ccc9b74dcc540a94337f059a8e006d315f3769dfc89f6d8f17b0f227c6f870df082aa903bd8c364ee2eebaa9036c67910a5be02c75754b78293e67009b32f9a4540681cff141bce9f3cbddead89f118c4e93a073fea824731a1b7ba9c7c5a7db2ea5862529e8c0c49498852609d4b630ed53043e85f9f702bd94c94486255a35fce1b4d4da67e7bfc945a7532b8c2135f43c01d18e436ec1f25eba55e75645ba46f985bb9058bfb13317805403dfe41535dfb5f137aaa42a6aaa8f1208da4e3d0aadf845f3167e2ffe0eb8a60e1372b441d8b19eed77d5b2c3c4223894b1d3eb3f7a5b3828acae713478035eaa5769962374a932141f1e9d921523cdc148253475520f6b39650189e23a9b980438bc0d2f67839906f5e26eb991834d2e40e8451109aa96522b620ae5f7e47b1fab3d836c0db786839e3857de5040e19cfd68aff24a52a2360e785aa342109baf91905e90aef58216db0887e8900eb2fecb05e709d13f020f40cc712ffbb9ebc4f768dde7b99d125a718ddeecc369e1db102a20957e08d353f6ffc6d63c039b154f032f62986d07377d44aec58d542a07a4f6e5322b9188f9e33a23e80dede0f11f2ffaa85940c3ad4648f7a468ce13d04a5cd19b487dfe93c8e42f444b6079d0b5a34559a1f8857f852796090816d088f134413651fecc59525978f8ec16efac09e9af5975cf4b7a10d86d42c5c2daaedb93c2998379d7d653da7fd89ae8a47dc00361f11012a70593314c84b3bcf472766b6ce1e0cc89852a629ab670bae50d4fbbb047a3ad276fe1b5542fea94d84311a7157570ed31cc232738ca900f74122779618da4b46727a911f6178d365699d4f63541454d5157a2042a99afb4ef193cb4d9e88393b0c2dadff1fd0406072b6e8adc0306375d90f0f20830596c728a9fd2dcf20000000000000000000000000000000000000000050c12171f262d37", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 47, - "comment": "signature that takes 25 iteration(s)", - "msg": "d908000000000000000000000000000000000000000000000000000000000000", - "sig": "146adfa049bfb2edc88f3ec741b4ee4228e0650dcd857e228a73d75b4045e9e43ea602a993ddae73048aca94065b0f9d1d96a948039c11aa0cb7b4f889acfdd80018d65161dfb609f8ba6516a0f4e02c7d872e7c10f932711815dbfb5e97d4e6b3f674bb797d163cbb4cbd4cb18387d9f3d1bba179b1100dbab92870c2c1a1e2655192b93f65acd488f90e9f0b84892ab424da6c54a2aaf09b43268121a77222164d88328b54dacc111e874ca83e7b9ee6334574a6fadbd2416f945992fd970a0626027c9895c4a4f279c34ed0797349ec96426e6dd7a7030281b67c343802d001da95e740a47380e5916d8243ddc39e849111908fea925ba424c65add3162f66393d0e98960b871b5eebe26e0d65790f121517189d501f40ca906f5931dc54aa963bdfe8991ee82dfde362e3bce546788e05a7ae8caa0afdd1eabbad61ecff6ceb080bcb36146a8ed08766927abf1b580939bc92b97638acfbcc9c45f9120423206ff48ef55462642c87ac7db6cc96bfc02aa9a4879c9c2a0182bcf611127214dc9e2884df346ba6303ee35f7b5476693331cd66c9cd0af8e0d48a2d8aaefb13bdb90a49717ea124534666b89c36d8ecdb744bbcf40b3f595e4d1403853f01ce8897b499e5a00581558e88c00d6614ce32179612808f321326505992b83b7b8c4bf0092373f3b6bf941f9f70a904b3d3fe293c932201f5758919dce55558f0c8ee514ce72ab6f77a8647a06d1ce4d831851adf46b2ddbb19cce20040c733e9df05026a3268c510b41f6893acc8592fcb4099ce61d76635ef1ab92e1db9c74daf9beab79cf084ec1734687c0fde1325b4ceebbfa913163c64cb205f83ac145b71f0300189f96b6c2d85efaf4cccab7e384e5a2c17b653adf56f4759bc929b4d6f02044675b5da39501915c482ff95e6370a2a0934a9c5d122b865878a84089ade99ff36261c917878c0b2433dd3a1f7e1ed4e38cd2fb0f3c0ffc86138279066168d695ff4fbe01594f0673ee1377ecaad98a259481aab261a2657e03aaafaf6bb7e8492d59273742ee1fd8bbf230e317ecf7b6c4eb316a7cbe7c12bf0beef149c6b5c14f949425e0cfb88556ea1833b44b8fb476d725fea447f722b892eb51a652e8d4c6d8028aeba63ab99119204c0b7234ea9e1e2ed08ead8b12fc8306bc20b139833ea79e737c2d723b70d885e17a6081cdc783e88ffdf82d855c1b527c9c5cf62d2d69104aa36748757d54d36a9fa0fe7f9e628b97e2234c8f61774cccb402f75b729bb0cbbc90617d9c06d6691950a96e1359be41f53fb27bfc0be9f6b3c02bc857cb99ce6f79a26c4b313779ad3132e947b3677a117ec6ed00718830f0c63a0d217f8ff5f725c0800c3276aecff3a6773b7e0bd78f9794e8c7fb1a49a15c99f353a97a41a2b94e354362b7bb0efef251807798eb56c87796aa860af74919b34e99b45d8ce7d924040b96e3ff1f9ed4b6f3b20b9dd4877168a55579a719dd867e837e333eb02a444edccde2c02a83bc2165ae124fcd07f4f6dc01a575fc8c8278effe0fd48d81670b4b66dd3e43e17273c86a544c8a56e7e9d67ae57632b1887bbd051f496acedf73a018f1a038a8e4613771ee2df56e2384a87f757941d707052d79b59a7e955ac14318d0cec0dd958d03fc101e579e49e1461612103e3d82d9bd197f7741f7200368b2021d8bacb5df21e823c5ef4cf630e180cbdfa2df9319778ca41d62bd6c680be34b739e63c7f89c780cbb0b4766a7c2de6956aa53bf3cc2fbaf67184b4b74ed5c13be9c2a0c94dd3305d36435ded9b671675ef0ab49783ad0d2d44ca7002924210e9df8db7f68b66d7b2ec1e1e785cf3517a930751d4009224b6cf078488bd1720d179f10877d265a07b64af73985c5f767ad3b41ca266feab648ea2a222b21e0322b7e361c611cf6387d6aa4e49fd9c187b99a1a2411feb937a76222fc9c85ada7602b8738f89c6985bfaae0e514ecdd844972d15090089e3e4c07be79bdccc5aafcb1a66fb1d9f2bc481aacdbb30d95bb0072f7cdb38f5617e8ad0cb7d5d60c78ffb53ad0030c48c26343401c4a5adea6d9c23480d7416b7efd5cc29c93f45cb22fe33fd972897c67f2f87e9ce22a1e1b14196e30db71a7a99b5c2f78ba77095ef2145105221f2636088796941a0aa54da6f145d1088e0f4d29803bf7c7e5527218a711c5b34dca0594879ad2f7436f9e2c453078853ebaf31b6e5531b5f0c980f199990e9c45e71f97986a18e2054a02ae43319511b1e0f84c93145ec9324c3ebd1b99f75a93e49a41113efebf323c8b808365aaf68e87fc596fd03de08e9397adfe8902d20ed3843e4eaf6ea9cd01e878d500a4bd3e8082f6a485bef2338b08458bfc73595dd8c464f8b9f80f0e5b4820b10483178ce5c7656e87a8d9d62df96b6ba38079ba86542465c019ecd2ae934521973e10f8a0cf9d1763a383bdd857504acd865d796163769507f4d854278e602eb97111009e020e999d2e7630ed165a417219b741acc575e8fd2b0c69382ba09a81d609b80774779c0fa9dcf345727a0c7de5bf35db46c7d0267990fbf56f3ddc717311953c6f673616fd4b4183749f43d30629ea5af696fe63793e80168c3a67db9130c530842e00b94ab7bfa01dddb04c3adca14c7597f8a1e070a67ece952d67bb631b8320472e15542941db28f2d5ea7a924d549ba77fb31f1056a843c61a383cc34d4415c23f32215a95686ff1d04d0e966cebff00d8f9a685166b792e7fbe1d98663afb0d0f6145bd411d1e9f297a2c442c945ec296b728e1702eb7c7a0c25edf5e2706ae5ebc91e969c4d1b1f2a9f32a14989a9310ab1e605132b0e0474e8b285bf2942ea73d4a63c0bb5443d7fe855fd76ce2b1b2f8aef7a8b9494acfda23d4a45a2d3c50525fdcbbd3a9a7c42db11679a150c8aa6861e6c368f5f285916811579b7070fa342ac3c5b2d65fa4f8fb85d1d79a4f93369afbda9a8aa11cf81918e2885bf94f0f7b13fd6945a2db02e6dc1269a90ac5fd00905b05d93e8dc9f8cee84e51c342fef0d7462f9666c55d06eaf8ad3d970090899a6a9e38c9b02fa0ae664bbfc0a95e66a9dd92fee540127bdd93957801aebc8a0845cb84cc9ed64f7bc07a4594345d0cb673624f73f51f08d17f58bb76a3661d877a3ea0c0cc01210ac60016ce5a46f0c659403960ed1ec6d558e7a7225ebe65ed75a3fdc125a795254136012b099105b0455274d22bfae655f6aff3a1b603cd38bacb88e797e4a571b118f9cc15827885efa34f2e400a3d020689ad7e8c57f390242ce6b57ee3c166496d33fdb5fbf0d9b86811a6cf5aec03104398ab037e5728a546b8a204d3737785807a26992b0a860c11ea3d9c9e7581c595bacbe31033531b22a38b839d7f19e1fe802d421fb98d560815f2ef8abd94113aa7fe6c679266feba691055b11370ec2fe138188805064f288957e85aaa0b5d0e950144275410725fac3b8fd87dabf5c260c0aa2cf94a00d545d6a1c7b43e08d6e3c98ef05ae51ba21177848ee82754a66db2039dea6e25d565de4d988f0e2a65914b06ea9587414f5fbc4970258f0c4261b93c44b5e984572adc18c272bebbab2517bcd62574fd22da85823aa4284f650b33b881e25eff1c9b8bc45322a50b443be55f06ad9a24a21c013435e4a10bcacb4132a7eafbad80e8f67de0e463c6d68689a2c07aec102a74ac9c40e5627e4c274b6fbe7d2d4eea4ea6d038f2bed44406f4e9c12ec5895f0a550b7f21144ebb860ea2ca81795c36c137eaf2a590a87e6647490ebc2d884656eba81eebe8085638a9fe8a1ee01e615525b34bb0f0da7bb791f7b1c92c7eccaed5e2b8e413203a919fefad0a8a6f3296b15f2887ba092d3fe73fce07d612bbda8ac1ef992732b6d3cb3739db646979529888fadb9ea3f8efb610a661653318b971ef0a1045fcd3e15986da3edd85536c360807fd8b10bfa9fe1d508300f098447c4be15a00c2c09560a0fe97e03a49c054f8584ac8d86851cb86cbebfe14c5dee0c4d2f8c6a862c5c204dcc078ef46221d00a18ee3c0142084102caa0fb55fccf741ee9ffe0ddee1f4e629647143ca9de53cdcff6b6e107bc2f4e17595f80a0a0b523a54471e106a232db3d32372aea59820a6dfad01ebde5b57f33b6e932a70fddaab09464c8431e79b7f968a4347c03d2ba9efb71b3fced4d4c72b6cc37612fa507389090ff42466ea0a3233094bc5731e9e3b89a55ae9042288450fc68f5e8053245cf92e9880c7034719d37bb3718299d5555bbef6db923a06a6b3eb89f28774e6235acbd75b03cbd89396ad7e69b97553c3e0fe7db13e0edfcbfb6e94db389a8688d14d94f18cbf6ff919c50934e36293b928e41f7560b243e5ce4cdb19ffafc4469b0ad9e47daeb512fc276c6cfd2808ee71bba923d69e184f09646d23e1c463a7996a16ad16b25795b12a295c5c5f1f4b9b9ccdef077a474f22bd8a5eb83da8e6b0ce571e652a5cffa32168ed072638442c675afbfb93cea3adfa3d31058681eadee484ad3248d07a63a02eb4312fe191c5d807c54e809d929e995cea1acdf054264ff96ba3580505d5364e289054938becbddb843a1e5e8c1f30cebbaf843d08092dc53de20b2ae0bdd2f98ea393f5f5cb7eea10b73e79017d078bd91e44373259a45521dcb3317dd3d60bb2b51e119677670e47c6cfc18a3731ae1fbc5b5637ed6da711dd029d716a3417832ff40df3cba155622c64c3dc94711b5d2d282371b859a67d41ebf320227d323bcf36f6ec0efe79c4955c3b7e6de99f59de4700fe8366c62af66620ccd3d2ee8b6dd99af8f4f8a5e76f4ece91a6739cf1fd3e1839fd9769be157bc704411821cd63e520d4a9919cc40bf0132a087f10787b38b4184b0750fa9bcc34177433b7c9bc9803b18d6030fafda61200732d9c6343b9eebc4ad618a8cebd393dc48b60483329672e8d0860dab7f966c38d4cf153ccc23d8802034c2f9098dcc60c53eb50717ae71c96b2c71d0f6fd2d239dc2268a9048a5d744d200040bfafa9697fd9ef10db46d0875a3084786000cc294df7f8adb5b9959abd485695f5980e4dad27ff0583158eda4e7226904e69186a95ed6882cb05cb806f50c692eac50bbce1bb6efcc1e6d52fb37d5959a2b5f65f9f4a2669cd910a0f88059fa7618bfa34a51a5f0bb470877f8a6eb309b17be61c77b2bd9ac0828e28bb9f51ddb64fb1c25358f3294391642c6521fc08bc769320b0ef772cb7bb969a7df9f24756f2cbd789c4668f35515d94224d00ea4f41a6c87b46446547a9e86569fc4775c84e8e36425d859c54dec9054505d171bcf1063bce8b2b0e4450784decd6f42428a09a1686a096ecee120e33a4b84ac2c82960cf8e186365a487ae19db825d2c88b22003244e6cc8b43bc59ae96ae71ab42fefa535ab91ef7bd4894defbbab06dad13283a2caa7683ec6c9428812c876e97a0cbc34aafae8f3e17dad94e5408e689ffd8ee3c4c01e5fe0d4dff41140e84a8a07a843b42d94c78b67fb440ff5faa0d66223d7bccffb09e0e91b81e8f36bfb54b2f4026056569ea0db33a3d1c3ee5e129c7d3eb7495a6339e76ea3ec2f71b2dd81d8c5fa3caf1cca95465badc2cc170aa965cf7493328349c255bb096c6f527b672fc2fe1adfb13d1d08301561d08544d4f6646e0ba4e523477aea040bf31a3464c0af57dba11c1fbc5a8102ec054271177fd6ec934496b7fbd5d98bda4604dbe7fafb01d238b2c8fd6df18495158fa37ccadcb2abdce4c0361d29d7395368fd03348f62e12a401e8cd087786a9c6f5d447398185f659044044047343834961fd5349c431cebb571d7fcc96afdbfcd4b17ddfd5d05df4cf47f65f7f19971c6b54400e7e2f16b81fc0e4e4a3fb3743d9cd00b02af1c197362c42a0cfc21e1b86346307685da346b3ec3e7d90558a08a090c5dc2e16b7b66a2e61c33f2522835bc15cc64e8ad5d30afaf12942cde120ee87e3cf2d4ff9f66a3415face0a4f2888c07304d82189cad36d392313fb5299a5f3266afb8dc8f51631a169074420c05b66cd60078283c02f47d522c94c28b3f200e8a431a9a1130005cc26061f145cf15ed3f509d157c515f9d40b044ac13411c2bd0bdc520001df3f836ecf2fac5354e0e6531ea88a0bedb7d19980d92aa88f4cd709790016575c4182f80a76115e01419b3959728248345fe431218627bba49e31e3c00ea2cdb58314815aeea17ddd875c54c9084c6c12c63bca3ca481d67cb4f9151da9c8fcdab45c27a23f83bf2b923fb0b838cd7ba74cd857bd39b5aaf255ef5cff8f4c186cf3bea23e3ecb39dc2cb661e4bb74be26b8313fad7fe1d04d8db2ff56dab2393dc844547337d81ec667a6429dd7dc7ce999566453c86549a433431ab6eddcd6e190ff9201f6123066b30d741f6300492010e29609cb1123e5b686a90af1b223f516592d3dce4ff0962698397d0e6f10255c1c8d902061d70de1b2f3b51628aa3aabee3ee0002131d474e99a4be0000000000000000000000000000060d171f2429343d", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 48, - "comment": "signature that takes 26 iteration(s)", - "msg": "d301000000000000000000000000000000000000000000000000000000000000", - "sig": "0f6e8ae515f50cb2007984b68a27b80c74245cd204b9d2d5fcba7ae8090ab8da6fa6618a02de1518682bfbab706072ec2d0253352a3fdaf640ca453eff83c6b86cfc2acb5c33f17b9e8b1fe9a49461ec23c01f4c2b1b6584444a07f7848cc8670e99fde7660beb0927e1c914c60a4b10b56060c43d6d27cac85fe8a3860cbabf376a54b72ad3890568fbc37419c498373ca33e1ae7fe8e821ded51b61d60aa08d04cc7f2b9778db46eaebee61afd3ccd6ecf0236226426b9f96f7821c3c39a5a4a95466400cf2844712298d056a4752428d9912405767b26d29ba261b2c758793a46d22f1f2319973902a55e7f1674ab6a4641eb6b132262d49afe5c9e7351e500bbfc032d4b1b9d41862114bb5e44048a98e9bc9b9c77bf628c44454992e897ca824f54b098d51d9bc49bda7d165a6f23024728a407e0fc0502c7455f7aa32706d7fdf2e0107c2ebfa79972985314be79be759ec738eb0c6d885663e01a34ef195726efc57f47cf7df0d5d2ece1ca3aaa6c021af5cf9c528ad6084104585272ea8180cb092551c1360c9de51630ed80bbabac6fa7b9149b6d9da272edffd73710a055db47bd008580f8a8ad68ba54a55a5ca8e69d3c94bc62089efbba86e6a66c7e328adf1918195a2b9a5dd03921d48109bb5dbd86003eb35c4a20d5b1d1a57f6a8c1c7d35848ed4338e9409f90d8b1b7a775aa048e5ffc31308086df760e24e0d1978ad7ec515c436b1ed39e287a05d34365efc723cb6f1410e8a6d11e4f3751b60c47ff17f605556c64329f5d46d26ddef5faf0b46857f5f2beae017e9b2bf9c81afb1ce480b9edf8288e30a78a67df245c1f5408f1292aae75f0c9200220084bf8c68443dea98983a5e04aaecd321783d0d124b1fb29b681d7ef50fef6e33107266d03bd5d334d834bb3e417b03bd2532420beae27884595ffafa8d2d9d2cf68e8b5ede988e69c7e233e15270cc889f504303cb5141efee014ac1d6116c0fbca14c7c2f2bd592cb0c17620983d4daaf9a700261b559c153455d2c8d4061d92486d525ce284dce8e014c6d1633a8a696863a948d7069627eb2923d7dc251acfaf1660e7f6efb5da826961d36d1f52ee78ec217577456d465394138280a98fbdd37527760430f62c89f5caa75d573e241764052c4cb94096bbf7b29c1fcefb85c8b89028b5581f7497c12f4c4930f20e7503a5dc091d6cc1a217ff8aeb64fbe5dafbb80b8633bad216a454695909e5984afb2068acd0db8b02b4f1d54c9e8c61d1acbb7136c3a42828bf4df383623808cbaf43d2562b2455c122921f2ad9a29d79fe60cee33a37d4b6473f8bd5341593b2222ade418ca438be673e8bed0b1afb4d8f418db81591c94a65cad511ba509c7e0ca02fe82f0756bc533824a9a0301402aadb16b7a1effa7e8f074b542c5975548ee32131587c4c04b1936fddb57309f37668ee1d7b489c76fd1c799ceedd92fb90827d077c9ca2b041f9d339d0e8c4299e18b7bffb078178476512eb6f94c21a07458f2c6f4b01f10594328f536eb79ff607452aa4857625cb3d2c6946720f06af3abc9a4642d1dc15a5c4fddd47daf273429f07ae0b086b024eeb592b2eabb94eaea07fe0e436b7a4ba6847b307769634ca24f3f9af8967a34716e3f9bd6fdfb00f563b022a0cfcf4380bfc44e1cf26cf61cc156159ab373eee0201d834de907e360131c53656e4084c5ffe356a893ecbcd6a100c8fc7be5f31bb504b81bb1aaf992c9be091d7e0bce952ff1d66d2210eb85b6a09b32b5dcf19a682a499a8b0b3e3414277a9edc6fd1f85d9d412f5af977705a0e6b352d0ff5a02f43a6030c3c80cb59d6e79b3de9118da5f5e17bff617d31e435431b62dca421c3ff4319033fb11f1a9f7c3fed098ba9ee995c78eb58adcb0ee97fb66e0d905570efca54756fba5e8fde8f409f5f717eabad0f82571c55c94d01fb1497b0e92ae3f46778d5ac230d1154c1f14af784054b302b03a021eac3a963b08289605f920d94a18fd1fc374387a1d6fb6a0c763262e4c20abcbdbecbef50ace7c5218cfae32b9734fc9b34fcda21a45f1b8eecacfe678925a8f9c50cf41b2d143f3f36ba9a125054e9ff3a7e5726bacab4a604f5cdb4e82039273a476e7962fd6645532d25349ce4104ab4eb083ce837aaff3d747c634ce6c5a0e9bf27d59868d5ae3cf9de432b9eee3af523f7ca7430ae421c7c372b34348458b3570dee8e6ab9b9e7df55eef68d4d269ed27b433fe5610a16c9864474ee1a6f06d7e447db9d6bf025d2ca88961db3219271c497f7da66e2165ffecfcf4082260da102557fcd6d1d6c0ee5c9e9587e77001a71dc3c4c6cd1a540bf8125f2adff9c6ab465f8440cc3500840ffc638d24a7a4ac48efacb7fe826b86945b61267854117fb7de60855b5884b0a557d68965d9c6e2d9f15de6baab971768647333b42813fd373f757b16d07728f98048103345c522a597bf0b8097c5e7f4746193a744464552e0bb2928f259173dd2610e02e3143686142cd566a9f631de02c33a2dc3bc40037a63c33b70b7328af037cccd6f151316993257e03745e5c44084b0ea5656881a1c452e60bd9ab33d034c1bb1f2fc7b700429652effca3436b13f037b3f10aa8613d114e27ce6b28bd1be776bb49d5419f89da588008f6f6eadc34abe4369eb4dc777483f1e7bd099ee064484d47c62dbf1e001d8d058506f8c6113280b28844d507b650e7263207b0b2f4b887241785b636a6456617cc52112d043d29a44bde6f2992d8d5b9f2327d09baf2906d9f79c18cffceba129c75eb0615131b89e35527cdd7c3389cfd5b76fd5a6280d90a7d91fc33923a3f3488b3dfe51a97f593659e01ae5d9063458db1b4cf1319bf1d967907c17f42f80bdf940db75dc6280f80febb7303c6da1ecde3eb5edb276c222818bef7bc4cec49b528745c9d15b019c3db789a4953e5b5753ea86c1d37be8e9f2a70fab19501e4c2b2065cf4b7a565c295f049bef2b820cb6ff4f9d6e14aa3380d0027e4946800ecdf806eacb8dbe727404cd4e4386432e0077038ff2a83a2d510a59922975c26d2b44f54a95e3d69144f79d3324b6ea9551632b1cdaa002560b50c420b68312d2af247008ae1119eb4db5385428af464587582ec77d08469ad9d00c8013231ae164d0cd59670de7acf37b84ab7ab93a764c6cb6edeeeb6b3d2469a2a140841e14d77f28e3bc94f6875013cb154bf885ecc63170d22a431f4a96767a8fadccb9cf0682eaefc90c651e00fa2ea8fae575dc83a52b4d3464aaa1ac85c20bc2cba4b279fb3d2fa361139d2d3a7e49602d17227e708245cd2e55c85e6f51195e4fe13c8dce7965b431b4dd1c6b3417478bfb17dccc645bd02951afcc0087d40244d8635b7ce8b118e9e1541d9788b3573df66acfc6aca9e47f44d03cc66813f9e4d863cf26febed91766b7131b615ce57938548f212d1978769aa51165e31a96be7f5f082e0d0e62056ed3cf90f53c130f4b623e5139ff7bf553eaa045c5656ff0de23eb9e6e1036ff355742fafbcd021856ffb91d99843d2c6671660603429a6a1428240edb538a026b46078dfbcdf3534784210ca244f638dd2644b5189cb468e938817f9e8864f4b9e6853de251bc430ad187ac5ef4d8c9a43639877cdae95ccf793c55a29fba7826c8f7f1f8e4d83564709962a08877d112cc8b0c0102f62e289dfcd2ae8dc410a5f899722980d9aa00e050c3fb4a23790b4237acd496194770325ad152f4e5b08dbcc39bc798df213021c46a54677a8506e1bf1dc05a5a25de02f3775b0da150fc94a5041d2359f0c9209b96fb5951255afc69cdb2268e1dbc4664f69b44b1dd719175bec720aabe7aaa4c397a8ac40c4929cdf2e02466fa8813db6f242c26c5c167a18e0bcfd21741e28523e8e5afd5328c11e95a7fa1e36dfe0d1f6ca8903d3401681f48f51e34672a8598e55bcf4d28463a884b3728b683b4f3933b8a18f5816ec45caa161abc43546164e548809bb9a5ae3ae53143d7632e4a9210e35db533380d1076298fce5fc176f446b8d9299364db83515f7e60a79794412b8e3b1d78fdc9de9e7a17f747d37384365def11c088e58996a2e36d722bfeb444adce32cf2596cbc21b3289842f98cb03130960268b50d03d129782be5cdfad5bac4f49a456542f8528659e0173a0bd98be15c681c471129386941368922b9dc90cd38feea0f05ec7717e023640abd9ea56ef9638430877bc9ab1918d4155ce1e24038a5ef3aa5cc74b366c0970ed408e4d2be0e6e42f896c841d1ee5831b07d2292b73083e49bc4bcc1f860bacee035c45a2749cbbbd3f4455a752edb021fcc6e0c0fd0476cba41883352a145fab59028f12943d61084feb0963e8d3a678b857b666114fa85d81464670a0faccbff1f0d41e5453808d5fd8dfd0a80aca109521b6d369d6421f9225f014145b8d3f3fcc2cc12835ba9dd4886b3e568af41ff98b5d9dd63e7dcc167cbd24321c60736aa5777f1fb97af3f1a80fac405c241446ec541bba745ceb4fac224a616fff159e2d7acb450aeb04842e0b01835a705ffe99633ae40c58dc8a558d7365b6ccbff5e853216dfeebd95bdcaf371b97b6f7fb3f455b79a7306663b0c219c0df33433daa986a8948794e2cf4eca9e25969b07d4ce490cc37e573da12d12233e5f551556c053a707a13e0e33da45b814b42505022d4300e9719ce191255b4474c79133864e20e68b399854cca034251a67f37463feeacbd65a7e69038ed857cad2cfa38fe7f2a571f80c66b1327955d260926afe0bd56acfa82cc18f305288c55ba00fcdd1dddbc1ec48f242ba09862169930ae83cc85dec0332e0074c9aab990d476d340c1064ae32c900a1cc8b72ed8d669f78333d7a70af3449b49f94e5e0cb6e0a4875cb398793d94e04065b996b0ac4326103de1be7316c67a763075a790a9d87a3c4e0cb4c9ecde0df4194666a6c5c1bb105211f0844108e6057858a0914fddda31faac491da6d889bf053246fbbc603129172b9063b3b31f647d575fb1dc3950c4bb3a6378afd6d244ab54d8c0232b297732bcb49a84a583f917a9e73275bd9c78db15b604db38b74cf388875dfc06fc4c830180fc6b4aea6cbabb2d8d773b721b7cadc6c18cee537f72353ea0c9550076cc272d1e116a1775262277292bd75053f12f4520764d3b091834d630d81f0c165ea6425d035e022acc898d850a2c889a859c52f6fda1d46046e75077f054aaf1130490f80d45fd1688e619e6a7242d46dbce60acef66fe9dc507fe1ba10ee7e7bee34420e0efcee74d8cbe10aa7eddcc3d96f917cfa4a4c2b532ec53c49a8f6ec5f9f0832e4d129a197782d75aa50c6a10a33778684cc059f5bb6bf3c81adf63ee68229bbe0918880cf3c4ce16472a76a95840b93019feb1acb50d7f7fef2cf38d0405e054a96669100089c8dfe04c47b5db72a84770c4b9ce5452dbcb9369c24beec8b4ebd5fa93f0ffb0aff6c5f0bf707888d557616a668fb595b552d8da3153c9f474104a7142d48dc41bfefcac1e80ebb970a1e57fb29c466454565b26380b8c1f7de7acc6645e2708c0e41d4cd8eee0b3d48aba8509b7294f776af8102b122548aae4e6614160b64575454cf7b0d4f327154e5d624599d7c76d3793d95ee62d65e19ebab41c796e9fac72bef4a7c357a08d16ce97840ea77de019dade9ece3fcfcdf60083d9a94a9b07752d78122006206e47d428f86827a0868da3a114361037ea40652c7360f6f08a314b4d7f9bfe9d560e08c5545d481b861ffbbfb143333ad5608ea1abba7a749b356b6df568a7fc4fbe6512bf5572b454967a46592226d7e84188dde369b9e9c7aff91ee55ede9ca8029264810d2922f6a716bc6f19517a012fb747b5eee909f1d8f41550e520e1aa8418750a463fd2fc9557ce6bb79de5f29fa479f2287a1db7bdb217de6e323e173358fc928a6b99e8a4ebae0702f648da79eee14f0c0f86de6cc6d887ce9a34ca6b55f8b55dc687451bc91f3b1a48da0729ecbe7b822d06d7176d9834881feff98c51cb9d827cebe4071ed2dc210765924aa87aff5c5f3b3cd00c257da4a5ad140edce481dcf6574b8ee368ca0a523dad0aa735df68b83e840f8d8dce8242e3788709528688a72ffa09e8debf28afdaddb1092a56d836549bc248ab657e33a9661b751cf2b3816911b3993322bfcd996b753c14adfe2e69e12b4306d4ed08a132f426a45b00b8479b61e43e70d6204aea7d6eea7741e255288af3e807a8778e842a902e2e7b6ee3702111afc60810b38f55410fbe01336a4f8e9ba133068130641a951fa0581478db6a1f2fea65c95bc56947016e1241b03f163c6e68966da91cb21c033180a0a54b55b4203d2dbd5498c0fd0ea927054fbb519709e177fd7204ce2a0b4d225b780e1a2030895f40d20273e6a80bed7f4fa0a0ec7d14b6870020b444b667a9a9ba3e1e421344559a1b8cacd444a4e9da1fd323848d5e10000000000000000000000000000000000000000000000000000020c10131e262c31", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 49, - "comment": "signature that takes 27 iteration(s)", - "msg": "d81e000000000000000000000000000000000000000000000000000000000000", - "sig": "cdbeb70a021814e395f0124eb4f3982a156677e4cfac9b5bf6140fdca92e27b86a1e5ba26d53566aad52c1891cffbd32fb6bcca10c4203ca2dcfebcb1c8b72ba1ff28dcb342c41c67df574ec517181b26a710015105ddf2e8ad7f36f00683e8b058698788007ba86b2962e0d2fdb0fda31fa4e8aa18e0f609f717176bc73b3412d4ecf962d7fb7b9d2ccdb98a2d4c07d0fcfbfc13f49099a8110c3b72604853db1fe34b16e851626ad49f886dd246fa06be45af09db66272d696f5d58f722a8572544a26f5d976eb14bc700fe7f71cb87b9bb086a0e72aefb9f31d9d56100247279c6535910c54a3207c3c08c63194d51320792a84f1c7ce172975d31e31bf334b36db705b619c9c1d80906fa08848f7a7e02542ea3c6ae40ad01eb0ca55aa9ffb896cedc057801d5a215efbed368762527626514e602bc45fad526903ccbb57fabbe6fd4fc3df6ea01a7090a045271dc5709f6b91091ac3a0d59130332a4a020a7a48928a22c6645f3086caeb05ca518222837589330e44046bdc9c180785ab5fca03b1934124d485bd2c2acdf93d0acd5d3e7dbb110baf4070a50351429064cd8f38f9bdad59d5e654963ef67e0e49fa59c6046505968cb3754e4ede5777276c1dbf8660c32389ee919d5613a28c7f27352b92e288a87305c5ea10362c7132fb76705ce6d74ebbf8903e17545ec4f0ecd9f84cc71a5e1dbe7a642af39a1048beedc302cb185d70594afdd31a49cf8e441d4c2025f6f110a928f41d1797b9201d0a03912dfc45cbb00ad83d13c0f9713d82f64d5710e54f0b92e3d92dae8e7cfe5f6393866c78bb9e2fc2ff5c05b4a2560ce0e186628812d4d5de7eab1341cbf10aba7aca7d7fde1840a683b8957c60c38040ace4d3a1ade2a11f70a136abfd27eabeae6c23b294a9fbda3fea1f97f42ff42a3efc3220d590dae6eaca914836b7f690cd50d295bec40538869a81f8996f4d725cbce314f8d476c73d56a25e02aa557cdf4f0b619999044440f7a157fca14da20e5151bc7ff4bd80fa5adf53f70c128a8ab0f93ecf41e848bbcd6c2a214c5e4ea4534555c82f1663ca4eeba6fc0ba0f4f915c732ae2ddfd92450829199d586c483e63fbc31e722d21e21fa23da1584cb6787232c1f1086d9a011fc70e779d126e08461da3b96a9843ab6ba64df0934648a003bac86d2c54dd0b4194f87705c3b31e86a1c574e549ab2ca9d688e4b8e619fd680b8b46df114923a2543934f9c99fced2358e249cf40c98585a1ae3c9e501d4d560759460385c9f84b04d92aa2181b84cd960e4ad161cc82c269295f364fc9e52f2685b5e9e3b7fce1feca8ca15330bcbb311d84c4bccbd7529d612c58a4d793341466ec6d668df3352b1eb78be29422d609b4e04b094de0eb3f6d1c5ee40ccdb3e12edceea861682acac5c9e9ced3625e85ecd5aebdbe3cbd5c40e45523e88ecab6abfe4e62dc147e119e429f1050707192a2a83b05be11a4482170e53e1605ae12ef4a777e0916a76a4eaf298493c3f29d375d6e8c843b0a257becf9212d415dca4df3f72a6c155b4514857ad87e9501b10cdee9e021b8be4f46d178d5f5bc9949b7a7f758d3f74a7e71a02e391e861811c3bc85c7aeed9f00b0484ccb659c51981b39694550807cc9608d3429f7d4dbadeae30b0fb057fe57ef1026a23fad4fbfb2c2f1f22662ea4182222e6be9c36ba7c2cf89e8870e75d5a56113f934cd86afb6abaf8542b640800e74b66354a60b407ae757bfae93acabea0594a9e518a47630e21f472f7cb5820c5d9f3330ac99bfd3e42d1b33282c4d4bd4172246def26e1b6e8e441ac35db410428b4cb183e6949bb0d29289705dffb0a5be232feaf37fd8b14c56a5dd7e45d7d9e5c0c4d2268f3c3425887ef44690b874f55bea2ec9fa50ceba423d8c3286c792f736b8a3b88024f123df269dcc6b63aaaea66bad54564f964743d99d6067a6195f1e92c5744a038cd783f7e538c03d1edc0186cb2ce9bfc0c8483ba3cc249431c49785236f4a00c67d165247b676087d8691d02826657bda47e9887f810218f6a31ca07befc20ca824dd3564538b063e93bf91b448d8ca8a4750db7753e7b6bdb5d18d0413ad218a1fc20b264598415d7a11ea4fd28ac61eeae7f7f91398f81c7fc4e9da2502978ec61d8d3ad8795e94a3b4b87ccafb8809596f5c3b0b16b5abec9336b21bfb94af913c833846294a27a1f44d614a04b930b6e339c5580c631629ecc1cc4a4fc0e800df6a897c0c16762e903cd9c52862ed251b4f466294d25956917cbb29b985c65dd36825e9f78df5baed6f75dea5fe856300b23b7fd8c9fc60f138cc4c6513b0b562acd6c3eae36e998b98c27333deec77ca8afadd1813eacda79ac027a9827e80b03e40e17b84759afdb2f7bc9056186d060025f2e7404b9630345358000c9fc9b62f49f98ca11e720e30164db5ec43b092cdc59cfb1589f162e654c48c1d092d6fac6e5d66a430e006ef689bda62fc3420af7c94ffd14eb4520347af541e66797fb7f6248d20cc3bc432a92464608e94b8fadbee74dc0d4af18ac060a1f5954236f32afbbb0b308594ac19db18ce2dea0cceeec5a4ecfe9acde9538de355f72e9a65231d4ee6fd3f108619043429fcccb3b0ac2eaa5ce90cafefafa2dc76b565ac054f80dd867994eeba7f5721e2cac02dc6b5446b37eff24ab6b394d417e70b93cf24932c890f176901aa2d18d60a87ae870e2d93db3fe4cbeb4e6ef2ac323151b70bf4e7a62967bfd8f285c837b18abe8e9d5cadefb4a61c626065f070ef736d802d82057306fada5b6c3dd078586f9087ac8bc65d3092ef964d3b3c4974ff4db004be259e935f484c0b94e368fa5e31a07be27591e2336a9f734fc8d037f9cd283b02fb49e8145e8ea66bf91147b2475cfe6112f2c8329cdc857d74f8a0ac3268440dbde88d84d599321cbe60bb43481306c1850829dad9aeebc730e4ae05b7fcf9f0d1d442134fe7e4923fe14e4458cf909cca5cbe2021b281325455691633d0e68691f717a9bcb540a45a0e7de8cc6e81c582a37a6186dff567de951574135b0d9ed8343002eae17f82ff75648ee692979a862087f77d4e7affee83bc4201a4ee83b8ac2f470583ea94c5cb979d1eb462c23c47d250b18dd96edd5219baede650395cd3deda46af9533c6c926b5e3f22224d9d1eb4221cf1752b4bb5df18c57e989dc624ec1588b633d163461be3043be4f9f0b8c455e55fddec0a6cac72e9f3402deea5f16a00d8651d6314872b37cbc57de03310866e459aa2c1c0f559b8209911f07156f53cb72dfcd67f4b1a1a38ed84d87a5d89d5f2a849f329e0dba13f6769bcc043224d0b491edf6403f7acdeb71380b5e7355239c0d738d332629a7f8bc868c4b758a185cdd9c1cb38397396d388c621cdbced3068f0293acd5659e8022111be6fab5473cf303504cfab5e835c145badb58595e9b70154f90d637fe7483ffb3b558edf597161e2c12a4e6cb6276335eaff39e624b1d988cf9e33c9b13c9f8624384842892bafa1c9335c72bd452e144d4f5f2899ef4e5a35d9b97685d128822f33eff9b5ca6f97fe048ce85ffa68715913fbc6f5921c1ef5a4f80d481f79d2c8881bd2214f85761a45340abfcdd8176d6f01865c005a29bfe7a9760a5991c3140574d4714e25f7284187c8d41b3cf46d25dff30410b23c439886fba1781cecee392917078fbda41c7a4c4cfebc2c01845dc00b96ef624cfe843df27684425759d47f7157aef83ff8ac99761c9074959901403307c78ba289037cc06410338878fc9abba22aa211d7f439765ca32ddd3b4d0a958d15a846dbeec5219f06f955b4f31dcb0a1048fedee05134c5f96bf4efd79c04a5bcca83a4e39f3dfb52cc201a12e69dfbc427a8f2615e8c894df27e2d4cf4fdd5fbfcbdaddadc50bf4c4f88a6d44be8fc953477ef81464cc4b4f1bf4cc76be9294d544fe5b971f21204467e265566923c3910c4ddfd434d496f55d2302ed4735cd0639409326cfe341cf32e2a859d6a4049674357028e4820237b5b5ca39329a6987418f00a8e643b448ca2b58808d5c2de3d319e65778aacc69c7be548c83bcf9820edc137a0e6f2814bac6c55b744ee46349ed1f588ba0854e8b7e24eed147162b950ae43328974485faeb47d27b40ebd4e53aa0cadbf5e7814ca0ec2167220f499eaedaf3dcd0fce8920d072d6b5c4d86d7ddf68f9d188bec99136d2e41a4ee86a23fedb7e3ff5252ec27ce80acb388d5b0bdbd02b69356b69f282dedfdf5e36ece9d907bbcdf4f851dda48b139db00724c726143c6cdb0628a2a5e053adc19b02b9ef2cfa4b7ad3f320a71d442ac2dbe1053ac0699318f010cd3b4364767809ca91847d2da66368cc55ee8a560d5ac58728188dc60113de7f005e2b67ca937ab6c59048376021b6643c0dd17bb3e2d5487463930a7ede7d1d302a7944a316f1ffdacc1bcd21c185c8660241edc57002371be6f8f2dc8da9463d53d623d397a34f860b3cdaed6d46f6b0d185185ed3389efea90fad6e27ec897a6f308b2363cf502eb5b662765431bd49558c8f79921705dfa5e5aa32a02ef4de7fe2b8215d756b066323799c86de21231d52cc1f6c3ce2eccfe16e085fcda471ad2e45c79e12016ce0dcbb573f2321e1a1bf4d73b0c3a5940327d1a1e2d829443ef06c48f26cf652e6c86b9a765ec4dc87d05697dd7f77880d40cab0f4292addcb17ac0e79ba8c5abff845cbe7cb956f223540b8bdc290f8909923871711c0bf7ffc5e45313245329cfe9fa0b03292a8f8bae6b404751f289e900912e810e09a154ba8bad82a8d34f21fea37cc0e85858dad77587eec50d20ae317d7f1e9d2e7b629b71825807786b7dc2f60d144677b9b4c18790592c8e2bb7655ea41da207f1ec7906a50306f9194851538875a9378551438439d1ee01c7657f8be8dbc24157183878384620d028c0c99b937d41d79128f2b168718d8cb47ee49aef7789f39a2db0eaf10ff46857828b409f82d98fbc3874d36e703a9f9d87712160b167f6380d9a24437dda6aabeb89aba2b9789af24d3318047271bf604c63e57b67dd01b7d03b7e498d58582f3984e21a83cf707f0245040a7a844b798920a3a2e055af0b9c7c807477f141a3de86a94b8e09edb9cee83fdd2d4d79bed5f74a5b0b91c1195d0919ec389888cc09cd3a47b6c4587cd9dac56252a64419b65dc3c2424568618db005bdb9a8b2aa949b26415619fcc0ef795daf4fa96cb194cda0c76c029c02ebfb577d875e1a807adab27c7f99b1ec4e30d53e37dd3984ee82347df75c879191e444e8a22e1d5ac5887cf3e594086ea51f32b045a5a903c07d1c5f6ea24f6abeb3657cee8c1897b78b8b82c45b7a29b99b65843ef983675a5fa4bbf480cab3bf418f3d2dea9d9838d4f5d4e49a7d842736e5ccb2d72b1a0a6f788cda2918fc733d605a0a5989eef9389d3dd1e4105e22bc4bd746c4d562a838b02621c04b6005cfa9af85811f85a69d7756b8e3cb1898d70d39bc8d31c1866e0c53540125cb5a6dcc9bc2a20bc91087e0f4faf92a042697601fc69335e1b603cc7fc279a06525fbf47845661711672faa37dd9dcb1b159937c09379c4101c71afc4b854448dda600f604059b45042d06d1e80d4dfda34f672a57addb3bc3f90849d7dac54368e3e3fd46906baff532d54ba52eff345f631ac6dee517900e3e15122cf5a11e1cce80a70c7d36ad4ada03462ffbd4706a5d3d3562d16560879e7d7c00c65f941e82a86be18b27ad22b73b875819c8721e92fb85f977828424df78e94bd7fe9140ce250fd7fbe0675ad57b174b60975450b9f2ba011b325605b41d88905e87f4f767ba005cb733ee630729012c076b0407622c84cf56f972e801503e92ec1a860dc75b8cba5ead473da6c550485b7c0a12ac97a00c2c33ac06dee7e5606167ab28c1fd132594afb64f837f1a1dc8b6a44019b3257843213ad66694e4199a313faaada70a1c2263d9d5bbf71b8a975fe19c6f26725c30b2fd25a964c3553e05f6a581c83fa2a8bb82fb1d1528a4fbdecb885f1a05e7e7f11d58227cfdee62f10e62bbed4a72f27cc02f03cf33831995b754f8d56109aee6142f210480f84844ea9dce3d1d4338434fc6c30e8683621bb78679c0e02ae52bf3693e1ce61fe607c20473fea107c3d13e27fc729a493f532aec9be4f4ebff583af24a0a0ff96acf7e00b8090fb4720030de53918e8fc4d8a716d58af7c962c1ea9376d5f44a5fee5e3700d6a74beff36568dbb1bcd1b5088506226a4a809c831b1148e131b5e778d49f9feb659e472b98147bf1b0af02c0cb7723be291d56f4d3a8961bfc9366bc086531016ee313c93a3af439d228d0ffcd50d64f978a2e8ead5710b45407ba2710775cd7845bb89c2581d895d10367f88dd414c4e586973d2d3de04223f798395a4a5c45b6ea6b1c91137617c858ab8c9e9f2f6ff1218416f7622ac3f5f667a85d2f209171c23404b797eed000000000000000000000000000000000009121723282a313a", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 50, - "comment": "signature that takes 29 iteration(s)", - "msg": "9b17000000000000000000000000000000000000000000000000000000000000", - "sig": "61037c9530addc2d2787de051b2340d604160541e39504e680b92cdafd26968b689c58d11118f9de074d23e3f3d976cf4409d1b0c7073bee681bc5d3e4c4312c829fd7658a501d58579748ca9c9fa92c1341e0109034d50195c06389cb3dda31a027efe06a641ee79a89fac23604e9ff37756bfce8fc1560bf4396e762c2e283610fb209954994728280cd21d34b0e3cc3f96ff19805957d8ece29f62f2a974cf2f643a01743334bf96f9e32a4449a61b45a8092dc1c08d11358b83259fbcec6ed45691c7ff1c77f0e59e4882411c6d9ec237784c26fd40639d6bde8fa441e51eb42f71b34119263a656117be3fc6d9793aec0c705fe34a0be5eecd975ee76ea97b2d19bda95b9e7f09588483a3473d381a7af6cd79f3fd67bec94f311cdb2662877ffa7c919db73eb1c0d2ed15eb40e73358874b5bb4794563524354ad3346a76ff19820b9109d9c92ad54d1a4be83d4ee4a091eefffdcc817e7fb6265e1cc7067c873eb5e2ee7a3c833b3b7da8d8654fb3066eb6577a26207527fdbb517eeaf788554eccdd914b85b958a93937b5e5dce66abe9ef73433c4d8349ef9b6aed1c8ec9b93f82ea902d54b871ee1caf3d39e3e43aecda63aac238f645c6d7dd95ea82ccdbc9ad09775868cac640019eca00c1169d76135014ab285fe89179887858b8a393597b3ff5c4d0f2258d2f71c5a76f7c723b68ef0aa6f9780d6b43844ad82897a269b50bb24a406956aea018646be050295aac4a11e0ed0b49664f4d660dc1bafd2ccbfe73a0db0fdf613cdc720b26f229eb476786f42be21ffbcffd1482c0a78420f07ceeda2f9b2692f75147564ffd197787e0f77e35de62b2b411598e5fa16d4c4c351073d4f438f554bca40ddcdda22d15a8b10e3081186158020754159d3faa489938ef47777626ea71de720dce9a8132766f2ff19b56f7ffa0fefd77d432b356135434c5b2077934ada399b17a28c057d6cff2de425518b938f81946d1171ebfc3243a19d6ed885ff12edd1ba6b408cc7e6aaf2faad32e1b675cd377c3c5088c53bceb026c8ea4491d5eff9718cdb1d605b52020a47eb3ab6070729b5e089028970160b09bb2b037032d968d795aa9567e7c3fbaf43371f5129713c52beedc79d91ca1909df69e33fe46b2289d05143f492967aaefe30784f2ff974bdf26dad7592031e440598fe9c45c34a7627ccbf385495e5aa2288f4118b35eb7c0ca917c6b975e0eda6a777c2803327493214ab468a81bbf996380a7e3d637cab8666fc8285b09c7e4c11d702a2cd69f09680cc2644031107f3edfe203bc86eed3065574a0b3fa4cb1f4fc1ffe7857b8c0f2c1aa74498e003028154c76d95829cf26ced6558c75639f5d38fa87391ceb6a7009a0d7bb65785e3c5230d13aa73ceac0772869e767368be32c39a0bd492d7e608e7c12948fae1212bfd9821a2161b0d02bf7f3ae87336e894f6d11f1730552a59f085857b19bcbe71f90cfdf245c22d24b71b7aa64a2a9721111c41cd173a8d87b200d933ea582846774cc6c09109393dad655470fb39b9df15139f19c633c844b142aca715ece152fa8031154b90331e86e3d865610cae84fc16e89f1a146e1159d29ed3e6b6a2a65e0156b4a36c16d6f3dc9228b2ed96d544f949db7b6841c02c038f039449c7e218a180340668bd66f1a4200e4b626db7209a0c460e24ec2dc28fcf0ff68792bbf491658de65299437713bda3d3fc3d4c38ae316ee4700930b755efa54cd66b5101f6794c73e6f212499f44b3a868b888173c0cdd947dc496499cdd4eb458d823ce0d753260545132b216a3bda8292449d21e679b0a3bebe28db10758db930b18e4b270968b9139c5bdfa94c6b772360ec98e07cd208fa3cfc3da897ff20d0bcf868152ed0a2e97df7be2ab6d77eb0acbf684c1af25240260b89e23beebda5be012c931c34c32f43d1c825ff3c2a1d5096e1a955dfc1b8cd666f06c2938c4fef12aff1216d3a1bffc4e6547eb493616e139527e488da2b56ae587597049c97a6a47adc39c15de2490006a8b6ee6ad593fc1dedf84390abd2b5c3dbf2867916d69996cbfb4275b3bac060275502e0f0e0009f747e78f804c574322a8cbe0f4af2470597e0e35da91007bfbed1fa4d215faee21d5b43f4f36813f00c96d1317eda1098c1c34d3137d417ba454b1209d24c1bbc4ad660383a2a04caa5d20655e757222927e9b3575d917f724c7b8946bca4b97c3ad0f618e4e9b6d59acce778b2f2f24daaf6c2a40778c6cd4f6e0c3aef7b993f75c789f463320fa7b291ec9c53101b1482d27a7f6148924e7acce389c3492b7b645e8e5ea8894c5db1ca21aa691e91bc1b844824a900c8fa19ede5d7f7d7a2a8b48473b2e8d268b59d52fdf1a756b99ed963ef796a232d18b106618704db57b2e371899dd0a4577313f9aeec69b0cecc9d4b115519b3148ceb7ac8d9e71e4a73bb31e3216d552977efea117c8a7da5e539e2f288d596585b4462ceac1bf0c1e39f0b187a62a517cf7316ed657b674babceaa34bca7c4df125154ce2cd3d124ce1a57f6cd4e975024116ebf5a70ed6f61d8f9923bb8f597481ca5879991c2ae4da0f7c4ba8208df9b1946e3bb4df9e98fc9eea5fe8a6a1c8706c5824e015e6eca2545b4616d422d62bafbd4bbe1772c43a90f43e286c1d5dd09a324e0cec036d9df8b9b65ce4f3157e8f7bee0302d4dba4c0b86e562b431269206bf94dd347e99a36afd2b3e95c9cad4981f33d51559573ef5cd092d35db4272e5c24e08acf7beb023a1a1c72e4daf69acde3ccb1a13632b9a1264e034c8069bb376a9de553457d9230363e6903f63b9ef72abab514676e2afd2ba001c8a5ae8f377af357c7ec3836201cd68d1f830aaf879da839380ef5081858cd85379fbfc328c55f7fde8c40c1a2ef81855c62cb876741f980d5d0d96080b771ec5ba6fbc4683d86d9cd960342a38b63d31a3ac13c7be4778b208010cb942b50cac76587f6832ea8a5bb7afc6b75b3585cca52672dec8352568fb3fb928cb3a0a254306a966747b1a8613303183086e76758eb11c445c17b323dc45de753a18d6caf78792f6ab2f3ace158ff8ca6a5e0889437bdb71eac89e0b71c15048726bf232a357339bf7b663d1b94cc88936b51e1c2b991a70cd90fb8e27b27bb869703064cf88a1da92b1585221fbd3270c11c4b97aad10e99516f99afc85808bc43301c40f8a0efa799106c1b918ba836a92940df3d88ee7a647f5d39f4d3aa3c2fe56b422b8415d0ed2d09b8f7559d0a58bef8610941be3967f365832de11fe8e7f772cbd44f4edfcfdeee43345f528ba6cd624b9c8b10ac23053fb87499638dc0ec675f2edc12910025555e818ebe302ab099f40d8fcd84dc9f65d72b7a7bbfd0c949242e70fe2fc1dde93af2cadb8b474870df3f3ebbde4733cd004b869273b21988dbc8052201eb544b75385428c4246a6afa737128b9c9d9277f0ad659949222fefc52da28b1702589bbaddc482ca998ab8c6651dadae9dab4c8dfe1e920beb1cfc065843c5e992c928bf72913c048446250f227ab13481aefd632978959bbe8c3a6b35c15d675cfb1310bd88bcaa13909c0b4b3a634f4a553ac70e7417c5b239759446c680017837f3a9edc01cecbf7e421a3baf0e673bb63f703b4ced708b4edc19b6a8b4808df5ea9bab45036376d89bdf36e0061b9d46c0432816c625c6090d4e77b333ee749ab3bd1f51e060e0a5f5c35fc56166a6dc43d94701580a42163b98d053416e467f5635718c292b94adcfd3dedd11f2c81df6080c6a971e683e998a6628bf29c64d4d95257acdfbf8f08a8d1646cfddd1cc29330fa06de01c8781f0d0da1481c12498ea376ed02e88d21a881b18f7684c1bae4f83e36d2141bc8b4b9750b20adfdae84feb2c4406bfd57c59fdddbdd1829b5b9a142f6af6ed81272b8901fca0cfb6c4ce12184ac9893ec27f165b18fa46d0c4c2c7296874807cebf8a8c9daafd2b17f59b687a0ba5ad9e3627c959680851f48c3380400c559152be8c5f17dd9e1e16ad00e677d3d1a890a601b66174775d5364bc42e3f3353954bb9ed7c108f21c44a339572d56db5afb3a391648e17520517f1c39c594aa89c15b653f58615f09079aaa8ddc5e4d1cb47a69c0551acaf1f2b1aac19f495fdec221eeb091aedca60e67297581817b6058ec89f7b70767ebb9b3f6af5cdb8fffc17148a160dd9a3fd25152a3ce0766d6e89e80aa9e6dd57ed5cd5b734c6e2cf68988dd176774ae8eba3e3903064c18f66c6854f412ba1e0d4f2155b8144c589a6646b7c57f1a50b0702b99b2626d85ff908612ee428a0be361f4b4a342a4c7ea5c660b20aefadc9980451ca571b3979fb42a7b65cdb9213a26a1c52f23f712a5fdb48d77a0cd19e4dcc7ba41e29709885275a8f4310afac9bf95324fd8e36e64d5f87ebe8f144d847917b0291376bfd9fc9ba871d578ce12c79b08412482f9aa632fd9959d84dbda6ee81f6f60640ea1f9d96a499874b701c174a3efa680522342f0450a56f701ea9129a43d2d02ea5a0a887153e91b32a02ad6cd9cf658f678d6b81d0cf9bf689a4b7a82b90d9873863b8502b05197d1af5a87e1a9bbacfe68892ffe15331bcc0b7c8500bc549c999baed705c2cfbd4af0f67b9dac3244875defbde7977402daf9d319560eb02ab52ba076f09a5d4f00674e6ec767f053c7be9b41ffed46b01abdb13f4bf66c26695f521cd56e508940913b515f31d480e69310b7403abda3872a92c36246f1a546d051a9cdee25381d2889ea3144cc50176c97bd8a7cedceeb893e8d97706b5ac8e31afdb1480f5fa46cf8cc1836ec36a789c8f6693af207e0d75ec90a4e5f50aed01b39e24ddecd2822d3f5b5eff8b61e8eba1cce7a37c8bd2ef896e256e79b102a703ef536b9e12c59075e789ae92abe2c8a6be2608dafa3755cb106c1f1ce34a4fd28b9d593cf20b6b55fb0d1b3114b244a29ed2779ae795e1e4a1244816966d43a8c6f2ce6684d6fac9d925505de77f6b3037243e7e9e08270a7ba6cabc9c0dd7fad846894178c820b0e20f1166f5bf330b8e8f475791af5ebd2284f2e3e6bf37e8e223dc4944787fa0c26088cfb572b7b2266c2129cdf6e504322e0f280ab1f77815825db08bbea2b1a092fb745045e52f6a53d9aa8c351a18d08c8f53f4cd1783599816331cd5556bebefc251c6db398ec009205aea19fffdbc096f33539124718dddcb5891aa1cc21d9ec8f57fcdbd5b8d22b15c8ff87f2ed8f4252a3926c46386c6e4fb18a1c5dee0953d6369f3b5f68abb722ac846e396bdcda2bdea2f735ae0e4c4c117a6a3ea43453c57cbb13891ab56b936ec609718981afc9964d0e9e088621859cd72d88a9208f0621ae177734b3bc42f8fa1b3851b54abd735d23a0662896e0b9d41282e7133fc93566f3848d4b171fd86c234dd48f8f9244f22ed6d02016da64101d8b8b3213fe8a6abf5d6738c2d48ca2dd47ce42c594468e93df13e498d4e467ad075fdad6b1893ce9fef3e1c06179e43871ce5445cd1b3f82cd093ad16234f075341720dca379812ba8ec2369eb7d95d42de986eed60525e268628a4d810ffe1ffd5ea3332d5e8c56ec66aeb499aae5dbe9df1494fab73f431eb200d312614af759b16492f2121d4440f5dd48f4089e36c1fdcce0711508dadc16b5608c1a1eeca852dcbc98bd449476642d415a8fa7df9a2df5ee8086cd82bb57e77b087c05e23e4a26332a84cafb0fe6940d7fd3d29df0cbf6943d8b6ed0f2a10035ed4f1152a635311dfb53b37e7e744833d64f7cf1e3a06cbd1d6bddb0dbc002255a81dbe0520f32fd00dba91804dc52abc7090ca2edad39091ccbb3d87df658cedb12d514e869cfbe48e7df7540c78d0bab0993b692d152e4f89266d0aa091ade91e92d5fd34658371848f128c2ee43b545b25ab32afa6357e391ba3dbf6e50b9fa5d11418156b338bd98e1525572ce11288be8b4f6342049e93c1c6ad4b38877571258dfacbee95e2ef2f7a86cbaee97201d49229453e7d05e8552f4e15cbdfe881a95feee1d63d01a557176dbffc0a4d4f1899bebe716151491b3ffa4cbfe6ec58d24aa1db81d793aadafcd08f43f28bb6a8c96d5e0b12e3ea11e2b46c827b0d80a144583dd18ee185f4d1ce645adb3bb7da4d35b2c432c7284f7d3e0af7d2175252e9e1dda7424003257223133d8f9e0b109cf16cf2d736462bd2b2749b5d94217def6115c70a44869378f3532fd64dce6ccb5dc3c828f9b6fd0afca0b0a8d6faed9683d2ed629763cebab8ebcfd82d6b24645813bcb404bef6143432aac82da7a0eda669bb768fc120383cbdf10abf6e60e174d7126c59609b17369196a97b890328dc778f27db9c8cec2c617a4621b5291aca62f75f815980f417921000d3d008f7b4364e8d27ae01719508caacfe9ec122944595f81aff7fcfd1326394f5460c5d1dcfafbff217ddf0708244972c5d3e2e7fe0e8293b5e0ee1c356e0474899daad7000000000000000000000000000000000008121e212b31343a", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 51, - "comment": "signature that takes 31 iteration(s)", - "msg": "7503000000000000000000000000000000000000000000000000000000000000", - "sig": "0df8b3f4040b8fa08e62fd98eae8ee6fa3cac93f53b593dafbc671b1d62f1a03c436fd08388335dd6b095be4a4faeef8b18eb05f4b8031af6e9a367d61a83108ac8141d13cc9e45fc16c6465aa1ec96a91f5bae364d133d2cf89a78af2f9c40edf9859507265b5e0e0a7def5a12d176f863ee1c8236cad7769650165dd22c8219e1ef174eb25fbbc4790d8e513cca1a79bd7cab20f14962ea65cfc041b3ea3db699d3572bfbb1065f5b5c2e0e7f1d1ea71db792d91cd787dff2a3bdef7cc5de73acff71ff1d2ed7c597d13405398ebf9b2dab3eacbdeebaedb6aaf920fdfef2bafa312cf982ab9037fa7af00413c642ae725302a0329b421a4b3ee12548c84ff6b26bc3b23be9cef683b105c03fa2ae65be19aacf1554bea475e5122dc94c1daffc3c5b4c8bea2a5d1cafda28dfb95edfd3a5af5ae555f3656ff545daf47d8892ebdaf57976a690cf212750b5aa9ca907449bc8bb3b31acc9b082847b834a8fe91b7dc01dadce2d3d85282d5f6f42ff400bb5164e901b953e711ee182c03a3786b6fe1debca57c4601e7c4ccb5144aa56b959fd21098141ade5f956aba4b2afd7b4134116ba7301e60456c97580c94199df152fbbfadef3208c58febaaa29b711c74b4a8e9fbda3157eb193e835473a35705c6c162623d1d3c013cb47de161f8233c0bd1f4a2b01ab4dd712db3f5e035df35cfefd017d4ab2e4fadec1a757599b72c89f998509350a93259726e38940db7d83d60c65adff0c2eccf908d94885978ab2e5fc0744bdf92994f0720249d40bb183d4243a4708ba289c254dbd81ecb92a8e24179a0b01ca176a6192914c854e48d2911d0b297e3514935ee4afb1275fabd693acf5b869f6e475c3508802ce53b608532c8b94475218e3270a9a95d02fc0287901149a8815de06ae296adcbf20637002f406906feba3089cc602648d9cf630a547840aa75d38defe83834997ed9eca86f5af0130ba198097cbd1579375e857512e2ed2a31b9c96eb09b3ca27a279b446d5f9aa8e05ea8b0f6dbc1ecf2707ecf6319d5326dabc4b2d6781151cb19623cfe2f6f06bc92dd0c0fb38f0fe6a3cc20d971606027d4a2a515e781e2a22283f916a3054553e09072baadb22f44963c1024b88c64c8f1e1129e033c44a70ac3502884fd99facce36d77f3178143aa62b4034440b148a2ad974af899a1e91cfd67eaf715d9c663571ab91a71cf6798ebf24d8c97337470222270a89020564959a2d3585d9fd9692b9e250f59a871ba625150dcc40b1ac8eece56f52654954aacdb5e20fc768900a06ec45b251d11473e809944e59c07b7a3476693474ef7e8bd4daa28c35c82456bd30538e4aa41e51df19b790d03c20bfae62f1def5e27b9494ef98a0cd0c4611efd58b365466c9e429f4acbbbf7635d37e3451dae686877594b77efdd7c01b787734c9fc5bcc19cf184cf7ca0bdd891c77a27b6ec2d9e66ca207497f18e7fe126572ef47c03299bcc3e077bae91b00ca69b05cfdb15612db809c6aa604b182ecfb94f6921979c81e9e61637fabb0d19ff66ed635e534d1e9ecec01c45c993badb07077aefd2351447d1f0264506c6d8ac4220f9d9ec82f858417d367de3ce3bda33d45c2f29989afe9cbc84bf3b7211ea778e7ee3b907f3d1b14bb0738803d25b8721ee5e1b089b81fc9909f3b049853eaf0fb31d10e98c9f9befead2723ebba9c220b0d74807cab3ebe0d5be7dad5053e3b984461bdbb82252cb88e99d7723ffbf4709ad3e031c9f611b231bbb57af3ad62e26a877485874b325e24fbc3e6dad606edddda3fb3c5817813fab2b9ccb09386a788e6471206819d19479b4a4bd38588b052269a167d2effb7db72bf145c21ec6e1e83e69b8cb0c81555c944080deacd0572237b3060031a687e886f4a28eb74fceb330767b41634ee6798b81a03a6269e8e0490b8dc4eb5b3fe82147574b41582b397b018a52666afdaa8f8aa841082fc424fc01a388c0b39749b12d6acee5f303b3d1f0ebc737bff7efc0f767dc49571f7d860f7e0f0916db184d0a498b3a1396941b82da587b00dd7c29d2ca32ebd4f8570ffa55ea0db2a511701800fc476dfa944d3cec2ec2f97a092db7b7724684f38be2c8e690fb0c5e6ccd893f0f5965c3529e878ad6ba344dd92beee26128eb62e3d321d819da1f93cbcdd4dba516a983702ebcdb05729ed6f2247bf75cd5494555c094521366e071b10ea4529ef8f30b5379428bc72992c97dbaf7238ea75b4d1b8ed3a2667f551ae9ebce8ecce9f0b4c4ef5cec63c8d7bf60197cb2f3ca8731c3d6878bec52849893a57bf099c00839a05fe12ba768c18f91eaac0ee26f9a116aebcd36e52666760946cc0f181448b2e4ad210dd60f7f992f2ac3786361910be29ad3ad559bcc470b1c64e6ed88f453b8342535fd238a0c1e87eb9887a3454c87df9254773fa09b4908a62ea826034ea30866c6f68c47ff19b1ee0829ac2ea855eaeef161b0b5452c66a3663ddd973df61029e01cc77bbafcb23f9127032035b5bb3babb5fb1db3fb7ae6b016726e0e06fed1d80e4fd66b7caabf21b5bd19de11b5dadb769168a274e21c35a0f401785dd9d235bfd01f0fc10fc34b9df72f4d369e4619dbfd0ca409f531a05864d47926c4f067b4fcc9a26e26249764377de669592a753acc9ca59472f71b759d25721b91f2d75e269e215449a8a8f7d5bdc788b7599731c5c4726c6119a5900bfb195b4b216b15fd9322311eb71ad267ba4ff6828869fb30c211b167171e6f0a8bb04fc28e3e7a1603d56e81dc7d874e41591b596cc2831c822d9a51fb8e439561b9844acaeb32b5c4cebee466035dfc52935bbe27964876b811ad55f135aff8c83722f2c218b9bcf38569ed0f9de04f337cdb6e242d565818c0c0851285b72e77c41fdb2b34efbf4f33dd4e917447dc591293db756cda3907c735722cee0357892f3fb5847693492e055ba6b3687da65534b5721297db74d0e10badfff845e31210b986bb703d2df5b2fdf3fa0388ea420dc569d6fb8b2f5e969be050e422efe352cb0345f1c3e76d212910e9cb304ba964bad1710cf5b5257c90a07c89ffa6d66213a6788525d9cded0b67c9c20bcb3f27724ed513b55fb05ea3b1f7562389a8864dd4a41eafe68be8384d9471185abe75eff8003b062d358c00e69bc2eb4df80d221ffe7526e43a3883e1045d1af11ebe589747ff828752b7a4b59268026421c45e4ae88a47d7c1d53d29ffebc9ecdef83a9287481141fcfb3702a931bea520e4ee585bff7b420a0afe1c2cbaa5b1300ed993237fd194ef54f8e0511fc615d93fcee92261bfe8972b0e968fa2026368cf9b711c6674a67f6fc76ae49a34e91aef97513416d4eed991cbb7b9a587d409956abe016ea234f5aa055ba6471f70447e89ad5fe85a6fe10bcf849a07579a8c02bdd6d76a2811f1153422a979feea9552f88d3b5e0226fe871542b20f664abb514fe41bfc1c7a3eebd3ac6675003dd8ee28f62488ef0af757742117a8c38c98708efd2df13b3d0fad57a566f8507294d933c61db3b4d0c39071f8a97a66afd805c04bd86f6c60396361e317ce5d21622afebecdd6cf4b9aab46688d42e84d10311fa6206fbc3dde30b9f0b0fbfaf027add2984306c5e2ee90a2b9c065ff0c3a2b98edcb9b710b00eb37c617bf478a11b2b9c1e09f06eaf1a4521bd4a18b1bc467e400853bb7783e79d7425dd3345d18d4340dffbfe42ca69a8770a9d54ea18f77dbe01dda6b8532fac57aeabe29932d6b65b8ca03f55d8c73f7ef6380bbe635e77807d6925bde6dd6ec6c43aebbcf4723528aaefc63e590d39a21dc77ae3ad820520754c9cdf2c711351dfc23d1dd77d5749fc9271c69af853686bfd34ae13e11861d933914cf502eaba87d4801167ca360724e25274bb7e7ceeb15afaf93319aa03738f551e9e6b4839740dcbd7085da7f0d7053a0526cc8d19cf74efab016ac31c8ed5651920e09b7cd3bcd4f7709521883b92e5e5c0d6e5bc8f2132df83eaadee6f4288e66922a760c60a50682527566731f5e834ffa26a96819c083098f15691bf807ad970a3fae6b1894fefbcd9a1cbcdd3145e90015a002477aaabcb5237bb3b74d251d89cc8e84f70be3fed51bd22b27b8a274223af34e2b02795156f295ba37677bdf33f532a582a905c08a482f01a46f40fa20af5e30f0ef2e0dfea1ffb4b1eb24674015744dbeee111549ff1feb21967e255613d664279ed862ddd33e28526342080ace2caefa4c39d3c2b3f5398ac9bb3f7553503ee3b16e0bd119a799bf3c7988f2514675cb50469fe01865948b108ffccd397e21912941df149763b103743262fddfbe71a21a64c1078551f020b21ed455df858fdb39ec6e4d15ca4ece9a583ef70855f48d2d714a6d9ef70280cfd336f7b18278cf32d7aae7bba619b28b0de19e0e258ea237b8fdcfdf8a67cd73bb025f35007cda5a6a1363cc1269837823d496b800c81854699a7bef36bbf2260ffdda834d99779de873dfb35cba8e5d00990bb018701c145f19495912b84a8dff0d36a3187bce3aa5a0c9d1e0d1aaa1ed9eff7461fc35423da5e47634f98580d647cb60bfafaf4099a3de84e8593824796cfa30ca20f129f9c731b69e9e1434cb3f742b56c1318a0bf05bd7baf12e84ca9e6ce7d3f19b7580653cfc6e57cea16aa4e9c6acbe90daad54391b6214058a45e7f71bd77d46c45f4a7464051c1526c3e0b8f509047de81d5b1aec53160ec78e8552be73491ddd3b3ad02ae45e7192497a491bf524562321793fb2037dbb499e04329bdae5728e54d4296215c0e0b6bd639c902b3e278d8b4acfd93bda57cad668b452ecab77cd6c24af5c71aec6e4b30cc6f7be6fac592903ce0c9bc4e32ddb823f47bb62cb28f128417e6bed28952aa2a41acee2cd8d0c41687092709b427f503c5fd00042aa08c90b010c835f3e195ce325b5b88157ce709f3df925502484474ec54a339803c66392b12d3a4f79187ecd36e279bbeea524d97b34f03f5b68fe106680f9696d60722094f5bebea98851acc20664667174dea0bf3de581479546a87db9f2c1b9d25204ef8180c505e2923564bac238c71daf5836061ac325a39a1ce5a1721e44d79ea3cd3dd8a018d2ec770a16e43ec85843e80c8da7177c75a739353cb075f06d67e7f83fd05c8393183749058a395fa6ce995d903b0be40e1b6f0ad33f948620d8419bdbf1cf9eb34b0fb3ff7c6c796b5a0c725a993528654be76bdb8e1622b4b7027a747bddc6918643eaff369a329e36dad055d2b6fcee2250f2de3046640e2b57dd5e06466af4fc3c58449dab05c22cacc67386f3dd2cf23b8c91d86e80eba78b77176d2b6b19fbe4e59b8299e6fb75082f1b0083f1dbc8c0977ed06b6bb77e8ce92c6f491e57a7c3647ba2e6e22e4ab3b62d13c98552dcc5ee245e826c005a1ef87f9c9dc0adaaecb67426ce08b0c221999e851572cee939c865880d3f6bcc38c44f146bde6187fadd3387466bcda5266ac3ea8d4731d27fb71ab6836e8be56db8131082b3cf7b09ecd590c106ef1de3a66ccd45280d7e5f011a2ceff534ae07364a7ac2b4afa32a31c9af1cb5653e2c1b62a0b506abdc84bd51feb2fa3697f0282fbd82093ec83c99e9875c1a64dec416034476af10c439efc4e42e5a6320c9df11817dbffc51021f58f91f0f7fa496bd57e942abf4e9f9d80b6601b7c0b915dd50a88ee056c9b92dd1374e0763e1d161b0c15190c670e6dce8f1b7d414d4a61124d5319b8e71e1bc269086a2e28b17739507ab95c942887dadf304b6154e47b4e73995ae7fa0363af69e6053ccb1072d7f4a6133dd9a491ef6b39d3859914ad9ec0169fbba0106e2adf8c2ce073e741e4b8df7ab75f7b9b71912b1a8f80010918f9d421ff751f246f1596fe068f6a955cbf118b2c0fdab2387a72c816c946992c96044ef71929e4c8b05aa61efa545f584c9f60fd8385f8822f31f4c835a4ee669a8e79ae7a1fd2cab9e834b350d7c12d295d9dfc182aaf052d22b9b7b83993b1adfda4775e7c7d144af908204df178ff45f926cbfbe9bb17fd48d52b8862d320f3c8852082c488a469e3489cc73b09d52241cbda8c8f16f69b21d51320003f44607e0f4f729f1f77e8c404a1da0dc43a11b9897cf64ffe276e5060f20ca18564975556635fd4fff2020fb7b9ff68f4bafbcb6aa2f60174cacdfeb6d2145bd5ce4a4e074646b10fa65d8eef5070ff3a2e9c381476d46629730231dd74aa9a76b530fce6a85bd1a9a48704b5f9e4539ce0198bd57dff8450220ac37d09934e3f8aa62b98de3929a74448af22a6a824fdfa417e9efdc959da528fbce1271eba79029a6b237dcddac088dc52743ad9b99a7ab451ee4b95d413be3a3aad41596e55d7546dbd7c16bd84df3c09cd9afad5944306dc203364056a2b9bec3d90f47484c4f5f77bbca3254556aaebbc2fc1d1e545f727e8e9aa7bf2b305556aeb027595e8dbdc1c8cb1c1e31a2cdd9000000000000000000000000000000000000000912171a242a3238", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 52, - "comment": "sample_in_ball requires 1 SHAKE blocks", - "msg": "0100000000000000000000000000000000000000000000000000000000000000", - "sig": "8243e3f28052056de7cc4b042fe1d959767644a1b000c5fc3cab98cd8d86670c2025a62784c13c5eb0f71b9546dae058ec5027d4e6ef29dd36e8ac6ba1dbea78cd5126919dec30e8bf50e9034aa5582d522bb97d30a7dbfb1af52d9cb655b7561a17a9df3d09b277849b0f4106cec822d715bc4dacea258f60f4b9adea3b394627b318d2f305dd612fa0826791b03c0a55f456ac9b8ddcbc67c88b6e07375e3aa5114a95afdc98e1167e7cb1c74bce4c835d1b47cd1be95356cf6abc3c9b36dcd2ce4b0267a1e0afc0cc9b7e3d0df7111efe0f936c79bb2ec2b3e65b0641373ba1096bd1006f19e0fda9c7d8082f5e09ae1673cbae86caf98cfe853a2edd27c48fffba468dd6808b0996cdc5eb50f7847f80e51f353ae9afc4a0008248901c25b5328dcae28617d3dcc9556f3e1bd86000e1630210bc8a6ca56d4f0bd61ec09b0ed6d4961cb56ff253039bc8f3b4f9e406ce7e408e8861e599ad05e238d214fface8605e3a3e2173d4b5e1456edced533cacf7135e0d212c4934982072a924074dd6ff9eb3985eaa4e108799c5609b936e2a0dcb32369ccf34766462dd2e310e561fbb09800719bdea3eff789b64b3602c2303286499cbf45cc769d8e955c2a0bc87e6dd60a94284fea121540966d1a8cb893695279771a12eb8b05e33cfe1ce5566337bf90dd241d9c31fb07c6205940b77f158a7250c5698d6c5c251e787bc81338f2171bbdeb3dfb29b2e9202c29365f33e18fe927ef0919482260c01b2fc94c90222ba4dcb14723dfbb3d6fce66da6eb6013bc455848e5c2e3f52f1bddc5596d4a5f18c8f9085b3f25b4d95f8497b818808e5628f94f03b4d838c013a3c2bae7498ed2f23449d77ce94069d2d1c50d12df6d8fb8c8f72b03bf04a3df67ce2990b56595fec781ecbedced215fc0d0b5e34c10819c242a122a4deeb607fb9d3dc68ead4ee07726082d132beb524ce9937b66ef218c221d77cee77ce255b5f18e7cd7c3e2ef9afe80c7bb6675128c90cf6b483d96bc6156f2b7a4d4c98097d2b3086519cacdc3bf35f8127cdd071136b889f1111c0db2953d4d47f8a9de23df6372d65e25b4f8887b4553ad11de8ffe01264ee810a5caac6cb214baf3ec4e5062bdeb0f892014e3551e1e8f5fa50defd5bbc7ec14839b1660d2b5afa5d67a945989f934205902b3c8d62a2190621c6fd3f47be0a69f68b61a5ed1b2c4ff03c7c22fb67a621a64889b1bdf1c27ca1c7322e6233d433cf9bf0ef2c3877bc9780fea6b1a7cc15af6d370e57ef36ddd0a612f1f7e25efdc7762c70c9cd925e545672ec8acdc77872745c7fee82c572d34c9341ba176a2f1e4e629bd1342d00d8bdbc12eaf17e3c2399057ff2a6ebc7834cc80f3ead92b86e0c9cd0a909eb074d97e7783074374454eeeee970e8aa7fe4c27eccc340adb62fc838fd23554554e62c0e4ee0a50a1f2cba806b6172dfca4e3943d4af28fc4e6beb054487d47f26d0d56b8c0f70393eba137c5f3c278438d264d35ff2225f4b8400ee97e550d7770637745cb7ca1cca4825cdcb9c9eedea9bccb9e7c9c2f43e5b95892422514890c465a4784ac10dfd3c3c5ecaeb4f74d7c7c1f41b2ef8a6e27879ce049054a3947e2f71a36c11f439af849bedddd2d4e23fa71857aaf34d8a082d034b3e6a438bd195e07c9d9a0d66a10a7c6a93bd9346314d8ba8ad5b2df800db47d38266b5052d82f7585ff57c9a4ab2f5c09f95b2e050b57e3135fc1b3832d86bde221baf6996c9a95e50984c7a2776a948f4ec98a21ee77507932e8da0fa1baaeeee4ccf34ee03f62bf3c267b3e02c327ec57c17e4cb2ef1be78e22c4090ec356c0c9d2b729b44e5d74d1583aa73de3d2187c910c5f30cb41586c014e1e44fa91c6155c646ead2f60e42017156326d8a4258addc65dc2fcf63d80c9d504d77222ce363b313bf396cffd8cfb802bf6c2f99e5e440fdbb374900b569a31f04e2ccbcaa29985e60c980b75dc8167e6526825005b07ee9dfe7df419ca5660315a5ddd47d70aa0a47e9e914f0160fccf4980a77a36fb78f02530dc01a88fc2e2be50d20f6066410671ad48bb65f4eee60b296abe47aa86967e454a4892c46d1b125fbf121c2972575de626b5b3320b419a58c844f6d0e4b4aa7308cffd4240aa4180f97b1241ff641d09c90bb40d4d4071f85b913a1a35421aac0be77db6c53e964537ca6ffd8795f21345b62d37a50a6544420f7142d54e6440864a0726172937974a12d775f69037266f501a9120fa31f71dbb64d562e11749260d4d3b3ddec8049199e0c34593dc34b7f5f51cdb963205ff57250d7bed8856deebceb18e8bec50dc74e9b3bfa359f43fdca881c9412fe5c791a7b0e0313300d6bd0b9b7177efffebb7aab23af990ca0fdea4957c2412ea51a7b72efc6be1aba08ed7bba5097be312b4cd3e684e47ef0aa96a5bc18da275bb9ef77f9ba05f4eb5fe1d8b88bfb7a8edfee8705dbe213005052d6c137ac399fb29c5c146bfb371a1f994f0b0563e5aa443167321318bb002434a79b2705aa24cfc36f7f748128bf7e38041a64cdc5459f2446ba34ce73959fe504587b5f5c2f91d2b5b9ded36724cf7f375cebc67dc5f3c5eb37a9d6095250c82d414544726e22392e9a7859898aacfdf18d2361f55139d32dd4786634ea2f59b0ea8db2f03ec335a3d8add4491c3377e3d5113b59e79360d816ec53834c8994ef04f634368d3d135aecaa1d54da5b63b606dac31c5969007e501360e60559e6f01c25a608724b13b978835b4cfcb69ca2deeb2d8b6235ebce9b0123ffad14c4cba462e47c54f7a5a93c5c8e1abe257e21ead4a6216a06aa454a15f8780c1632895dc497062048f04085e360918eaf7d800d4dc7b9907adb5a1efd1a982375792ea5c27d73bfb9f837dec8077cdbdcbadf95b02aacb8b88a725df65743db5a59348bbce2bd46a80bc9485aba23500f03890e8d114153bfd037a87d1ae27a7576d86bf435373d021c85a2a31cb1d978127f89fdcb7ecad2fef36de77ce19307e4ef1ad6fbf2c23224613868c184b318b77430c5e783ed0745c9b76e635fc808cbb62652baef12c848730893b7c6c3c713711f6d7819c8bbd126be7c743e66dfeef86b13ee6d74735edd1884badfa8dcad7107d86f841f69aeea05b28d75670696ee81fc34fa3a822b31a945141c56ae5154a56a04353e6a3c120d47ca11144d460005c75789e5251a225155d3655f6566dbbe26e248532ee4b5345c97b9eadb6f4bf629eca64d269eec8487efb7f7557052490d8fa144f5c0deadef6549cf5c167a02f208f2889d8cf9f380cea5960394ab163cad4b7a56dfdbc67be3f0e915ab030bc5018ac5f5a636b219aa00c077a22437d975689cee84b2b2555a3d5ff145ddf2a0e27b724265cd60c4db153e9975cd8ac5bb5658e5f61cddd821c31c349f770536be773ddf11b42d44fc22d5f954617b49a74e998459f230498e428927e875afe309779aca4bdab38eeb03fb8345b58ffac10a7b1e862e1fc9eb44def447a1e89ad707d36cd9d74f5f38a36251bdef3adc807ac384976b7c82133ff8d0ad5041116c428a45c9447934945def2f008aeac3477cafe3508392bcb5fd3db35a589f38c1b944e079aefbfadccc22061227936566c1b662c62d3816324582058dab11512eb1d6bbafac7cf7bbc4ff88801431ba5b14146fe27456e67fa285b81ebd34cf82fea2977dc70979b82f03d7e17815cf783b54e6e5096609653181c94dc8183c8b5561a8f8a3790f22c261ef3dcb7eb8c7a3eb0f432f016c92e0ee5084d121cfdd34b214bf7715de4dd6bba38d05a90806787cda65aa739d41d9511d7e0bdd9b6395f8b205be597590980a17f631d877a801c469f2e81fe6a44b915d89b04a3b35f087517be09cc2460af73d34b9c898ebe8dc48176316b3b747e1a8d6e0fd7d19753ca03b5c3ef1d0d9122e7c5fd373bbabec86da39fc3a223d3de048b2519fbd892634821dc195c011c078eddacde76fcc1a728906214e12be5901da2739751c2a5aed665b10a55b265e80c75e6d11e1d8ba9ae2e27fced1234b11ec8296eaafc0cbce4d65f1750a6fd82cd3fce774d66249d0d4e21272330cfbe89ab722ee78ea6ccc3113f6829e7d437b307b6eb0cec0082511ef8c69492ed46752523d5e4bbef2799eb76940f4035c101833f7059fa4c9c7765aa0d378c96982e47285aad8a2c5dc33303e2063166c10a8158f5e9e0b86fe152035d767be0dec7b4fc97313bd50c27bbd2323aee3d8b508a2fe395024cd8331996fed16f97ebf70ecbe997de5b8bb888ae8e522360097eed1c96fb2ad50af4a2a8961be88b46aecbcf31c573d5f172074f20e98d68be6129a1360a7c8dbc0dd74a21d936deb873d33e66f8d8f6ba73d8a05a473272b249025a8ad5740f7f37aa5661efe6558138d8487644ffc05f952777083ee67d180b80b1128a3a1b93dd3aee189f9eea635a49da7adfa127b7e2e5567e3e0d58efb6ae588d336bf38121e6f5494e66bc1a9e1f975d596468563f2af990bf08ec933016e9c50f086904f30ec130bf4a735d7b414d1726aa03222ccddef29b4ee69062e217928a00eb0dab678ecacd601ef33d6482e39bfcb04325289f7316d38938460e023ed12f38c38e08fdf6c75341909902408a5fe8786c25716683661f0060222db5d9a1188e9624d6eff0bbd3164adc28d6e09b339c0d825a6653503bf7251972f208cfdc0bdd1557f2f9892f3db0a9efc8409bf6c83b2e31bad172cb2dd95ae311d873bb80e642342814bb71890b5ac9e116f0f367bc85a790839e8dc1dd52b167f6abb3809ef2e8a34f6dde611aa4f75409f6c9e0bef4353d1c2c50df590130365e20204ffe392ee3438d644b8eea3f4a92c3184e232745957ffb88326b7846d4a64eda2cdd5b95412235e6420de10158930f675900f9b558867afbe6c182e37cbeb3625d88adf0dec9c8a3a096dca43b3c7e9eaa54384f4f987354407f2855f4ee5746ffcac55293d9187a668ec72c12468f588b7088b069b20aa03cd1ff3bd9af26e922922e327ba6a424eb0aa9180cb60da4c45a6b76aea03258818d9010ffb6ed4fd0e4453188513a15382e4e057708f4ef24d57d00968009c1022f3a40acca9dfa5523d7fd3e63603f198a5c72855e1b6169a333925fa5c4325efab41ca4800149dfdc8ce7635836978f797bdebf875294128f3ad72ed91ca8b52476f4c7e0c67082113d2dc327a4f6deee33bda8a7db96672b990614edcc7138cea1a006867ff22528f8eb7602720c58564cc8a9cff02b404355a03d60f03fa07cc74a6ba70dc4aa8f2122e5b7863af835ce5fa0e80ce1e62534615a240aadaf1e09f8d201559e19879f6f7715cc459229784bd67a3db8e6d65cf4b149b678a89661b3d0a2f22709347e28ba2bc4d4c408c7df1861266ae1fe47a32c22eea95164a42fdd9070e4403f5a8cf39bcff30f97b7dbbe54cfe09f1dde66f84be59754555e64af1d52508e59b97110440ae59da8cb70f2e7c551d3e41b281b80bead47668dcf8e7f1b2abc09af9af89f51c8690ac965aa2ef6ef565a532c7a0aba5520c41c1d365326a5d5e6f1b6796ccc828290e18a502c2fd403d915f96e01cf1936703ef01a781d7f48efde73d99e80f551768f1cab025f176cda4c9222a074426af4f94547b5108b89534344424f1985558111b570ca48955ed1035af01a507e93abb177447f778461a5908e5e1040b9ebae6d1d2f303cfb463d9784cffc3a95c6631b318ccd952ae9915c6de13374446cad492f84ecc36a4a95d520a76ada6a5437ee4719e73cf997b5a3a590a68356419888ddee7ba6db7288c36d5aef6030123bbf029f8ecb8302155d4160ff4c4c82cbc3f97b463791bbdd561431ca1fec380b31b5fcbdc920e634bd2b42eb8826d96b605a69c60c92a51359ab687b90b78ae6d94e51b64d721844b8b73a71fd1f201c41f2871e3a6e5d0b0e0050437938dc298f241974ae1c00e90e72e04c6ca294416c2ea243174076463b027addf5c423a93bbffa08893f9d401dd970ab0a907ecadde16a41bc95d492dfb8ad2d7ba7f96a98c30afe47011501608df033bf1d49b1b5135542ae8b0f6e556e0e49a9883e4632c6da8f6f4734e2754736280e0979faa883c5815033896644361363045923b8774b8aae0241f2ece112daf259ce072a1fb2c236913a52a9c2a9ad0b2e3a74a3c612a654f313b230673161bd54f9c0c907652a4a1e13677661fead894b893f8245525e6e39d43e5cef2f5686b07c94dfddf62d35f9c256df6c71ed2e4aed383cc6841b3ed6de8019ba6464c6db9c7c7156fe67b899745a65f0fe624b25a2763b7453233d522fd3a2073309ad4228452b84367d229831c86156df0e04aac208b9433c46d8fd03f252453505295ea122051b1c263e474d727815adbccded041f6f7c84cee34192dd0e252e33526f81cfd7db082728526497b3b7bef6ff2a42597f91c6d409415b77819aa8b9dcf000000000000000000000000000090e1518222d343e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 53, - "comment": "sample_in_ball requires 91 SHAKE bytes", - "msg": "fe00000000000000000000000000000000000000000000000000000000000000", - "sig": "0f706dade1419d35872d9f64635a31a88721034327f1e060484a5ea9077c479a19c2c120def41f2dd396db495b4be980f0d568c9aaa8c9163f294b8dfa95ad3cd1a34c3c7ccf6c63964445d7aabac3931b2ba97df8a9a2873598e8039e9b5468297e09b8ab34aec9e7b0fe643b22517eab014e392ec05e13801ddf1570e6638fa01de144e3f3426e5a118607d82563c282e3e3570d365d03cb9100c73a124e1dc2cc7d09bc2d6a0be250186fab21292764d9f00a51e1e9e884ac438d3f0f46a5a00ca56f4cf1f8655518a24a3365adb2a36c3c1fc91ee3400d2dfa75722649d450665c1938dd29f5c062409d4792d2362d3d1fd737b69aa4d102833e1d7914043f51131b020b6f302160f29ffbe623a5c1c7507ffab99ebaf94c10ed395cee6673b63f5679d700eb675f81f39a79ad2a2b61d742f36273510dce8759b490254d07e738e1b46121ecf27512210a6db52cf094949756ca83c10435044a30b582a0665c505f834ba8b38d6b4d903093b50ebfa29f7a844185e888a791b754ec2d7afca88dd0c4c792540d279fc084329b41f8f32fec5fd4ec60c2634e5878aa94c4ab7bacbfff66d455adce860e9682212f2cc8b9ccddb233a6c008244e7bc8ae13c8a70dcb0b2877c555d1ebe6645d0d9cb3b7115bcdc893099fe5f0c99c092542c45240fc524e94a7b4c078c302abc52a3b8723691b023953f1eda5eb9d47d6d9b8d7b8beaaa7f43f1bd8c3a6a383381d9fce9dfc163549a81ad8c76a46824dc52959f14823aa036dff9a6a168ff0936009c4ebfd45f82b14db69586c0c125a39677a3c00c47a920bd226c6074f34023d97949fad3572cdab9323bb66cdc3d53042f357d28e473395cedd7d9593c92f5aa3b88935447115752aa91bc0319f1058a02a265c6c985bc9a5bef225133a23eba35d1b82b67f20660f8a420bf33ca5249138e83623bb984276dd768b135d427d835eedbfadb673b011502e2943c5978dfdb095fe8dbfdeba3ae9aebe40f760e2170a03bfab1a00cf6d464f349d78d6b9796833efcc51fc5914a9ff65b9a855173ed99291bc7eecac3c15de330cbcd6791cd728e7f3e1635b083973044cd76006d57de9e415d09a251321d075da0c0da4aa2b8bef2d51feff4692a7bdc04b7de8ae379be72d519bd413df927f9796b595f23ec53a44d595d8aa2a9bbb9cc86a63c7fefbb5a26d1c30bb0a33048f53ae351bcfad57ba7c85fa2aa794a6f1c124456d61d0bbab0ccf2f5e7cb2c7792e5984b2410d32025f43ae328f6c811c356957a51d52e1e95608aa75192aa53bdcd8280f4d3a6a1c71e3612ed75cd2c9508464c422bdfd9f6415847399fb11d362155e10d83d5042589c7f942f0496323daa6d1df58344cc7b07beada65420a81be1696667b11763d2643677b0b3422400221fb805ff9707ec1dbf1147bb9c8a37ed188e2e4fa921f3c34813270d4d1c8ea8639bc766dc5036f57b594225211e7a0ff2da3424853d13d3e0950f555adeb1d076a42e0acf6bf2e0697f55a41cc10d8b7a9bcfce0aec867d483f712b795df188fd403a2a095ba7b9603a57a53dcd9ed27a5193e2f8430ad946ea637a5769a5acd9ec61ecb57dfeadc45f7ef7d75a217caf3e22cbcb90b2ed25a442fcd70fa425753fe7a3d05bf4279ef458b6daf388af37cfbd48904aa92b81ee8bc807c4874a3af463c95ef48274bb83917ac07a4cacc23dd048193eef17f42e5b76928ddfda269b915f950f8be94bf2ca6ece729e56d8871ded27bb644b2f90645f49e6d5f25f6c383842896fa2c94e8ea6b87d105509c9d289ca06cb7617c365056feeca21ad4ac3baead591b56007c6e1d596a11bfeb56e53fa48416e369997b6d70cd89a17f7e2f5f2f64355b42e6064ebc9f74698fbfb192be75772613dad7f64c2ae800452df4fd18b90edb0caf85c256c2a08837d26a63117d8bc844258e88abd9236aaa56e5a960e3aad38857927ea68932bf96f8267769c587c15269736e4ca3493c8bcb69105b93fd0a87305b05094a0f3186227f5c5d28d22dc991c5b42acf63626c5074ecd31edb45fc9e58040430a703c98aaff9b5b816599b339ab0ea847cb3faf8e19a61391cf3478a8ab3f6a935037a081a7a148e0475f55d4b6eba63c1871e77e753a5c67d5cd27aa74e3a74112fe21c9080eacf066d41f46a3d4cff24dada4b9a04a28601050e1d45a3f139f6b1c6a66487cd81be898427c540681699c7372b4e7340ecaed4f6f9ee9f49775fc9898bdb0f646817f197f2b8a90f0c8c1ccbda8841b7c1f37f3ecea6ddf6cecbcef84bc2fd6ca9b6e1ac354fd29e413b9bbb29716839609726ed7c15eac8b4d5977503e6cfeaf558f34850981776249e96c103ee0e9ce96509e356e5dd5d5472a0e290a39fbc91784906e254f6b10264751c0cdfa4219399a04b09f12d1b0e6b10815307f8a5623bc1de3963b2fe0ec309e02a970d292a17e1cfdcc63ed909f25278575fdc938a393b37daa3109a801b0ac33a82847a409f76f1b36a8dbe761e54bdd61e1bf6c6ee7af424991acf822f139aff6defde0acdb2bd1ef60cd7f2f720e9beb390d687f906374426e5c3bd0205632cd76145d414dc8dd129aa7ec6185f3b78f090a98d9bf8fd8d386ae9dc162e1492def2e9c736364480c25cabe26fecb3000f9c60f7b1960a4e59372c4ce9cbf4e8d49fc7b1ab05c041c7cdcd10c2b0b8b30d07c9b8df0aab4973e58aef70ea5355a3bf55d7332f31cdf1b75c127f6e08ae018e371548b1e7689f14cde807e9396c34b959989a58e78451753fba21fed7bf368c1fc9a696134a6da612eddee7c8388c211b156deb2757dd4e96fe7c33f0e1943a9da76a0a610ef25898762618106a9a5f639c0af53da69f662468d849d0b9a6d5b434b5540e7a0ec8c02cd3a87149fe9e89cbf509d0cacd6baba24ab7244147f4fcb7fe892aa3c58395ccd2cc44163f698935fbbf8361953880ec4d2b645964113935984eaf704962b12e27f021d5498a8d4b2c59260c95e4b0cdf598200cebc52bcfd40d5c1cfdec312752be4b456e16f2a350f8f4d28973e9e01df8716be3260dd527508430e4182497b205407bbdae4600ccec62da763479218ecdba2a4bc2ae33152dd805f3ec96c51439fd0b39b0bcd185528e78f11bf16b6a5b24906dda253c1279d80be63c292fd9c03ce0c5e6f3ed7ae89d3a161d9a82da38b5d570140f0f2c018a01413266c53fdd2f39174c2f587e2920f90c694b3db0b0ef9942eba891438c4403c678c34c2bb3da2cc1941982b9c8102598e766e7f3dbef222aeebd431fdaec213be315c5380aa797176f838c723e0f2801193e78ab53171240a681b093215b1d683e01fa5838ed06ab079f53ed5091cc0ac934b822fd9665a6bda21bf8fbf7f0bfee968e7195da9e6afdb39cce6fbf5cc23dcf61b0f9c8fc029e3ddae20e2281dde9acc49e91992556d66078d9eec1babdbfcdb4d30c8b6b7e6d73a203ec10ba395f7b9277ae491dc634b77e4ede2282a18c3a795820a73325e79be207339406aa5b24eba5662102af58657755ce906206f677fa4bdd010629117861ff8232c93e9a548ae5336b52c85f47f0db24919ecf0fc5b271f16bdc1df46f41ceb445e6ef0f4cac482bac77a42e7d66aa0b4ae3d5e3e86c3e4907441b0abca637b9329d6d63dada9cd6b3177cfe14be4d0dd73ed5b77edfaf0dc121befdacfc728c4c6007d70661c1e7e9206c69ec4a850409c994b4ef4efa3285b4c7cca12ede75233f5c278a97b091ccd95eaad3ea5e9e0b3d898ad7a49b560fdf427c1d616410062a6adcb01f937e3d24d7964190e151deaab36c019e8313f504ddd2eaa49858d8ef9d2915c51972c0b58eac80a6651ea99f52c24d21ffeb9a7c2288506fe9ee27f2b4ddd492ade9b53d01d6b1a2595d217e83a0e69f11ae36cbe1d475d6b33b2e02844bdbf1bac364326962658c1a3b3227660a6f6dc00875d419e2a760b7198b79d1e4ae2b4191c731208684b537f54bd92d78a3a37ccfa8be694cafafd51449c46d6e2386c4ab7c61558e44ae00c37e96af5922a4cbd5bad489ca15f09e05e309fb6dd75c1e506bc0eea4554af4e2e05142649f93f0d23a3eb6603512b47095bc40c81e0b9cf887fb0725c8f7f916887e8922f8bfbd59e31ef1d3800d95e1a0aaf089967989978c6b713c3f026a3dd68ed90559bef342ed7eaf27267273a9d88a8cf5a58747772b1519a8af31e60ad8cf17386b8e45a85c58ddcd42af60c1ac3ddc4322642075f53e9f9ba62b36670f1ef5a01ce462a4d37dd0cf4f75e058f574f0ae980a46c4b81682dfe6bfdce98a77cfea4c7363a1cd32316c65294c8031df54300ff7fe0bdd3e819044eb795d1d7dd69f4032b812ac22b199ae17006414b4fe74208a6b5dd83fefeefebc50047798545e6150fb5056683a16f2b46c89be8713c9b990a0cde311d8503fe22fe6c6143cb235cb06caca117af582aad75aafc8290d2e2723356548c06483269fe87906f29c7acc8b1ad863e66115b1d56e2d8c894acfbc3dd976f7f2b29af2f2fe7112ae99772ef2cb87f20ca03f2fc0a30b5e400341d949e7c5bb2b1e02ec1d2afbc85aa3c8336f3ba00a36f3ddff329566afded8b522175269f81052a8d9ec2479b8a1f3030bed4508efd77f440682bea945c0b627a1e60efadc46cc6ca431d02a9913ec812813b5da13679c2e33c2c66ec092dfeb0689bbff0698345b35afd3ef78b7783044d46052df4c6653e044777798872942f3253643fcc055e0a038d3b08feb36b4a82248315d3dc64edf547fe45af1e3918497fa56b5e60b6f92e1613b65d0d016b6f6750fc609eb696e2c301e9f01588523c7546f65b1207d9e951a1421c0cba6ecccfdc45edb28599355f8454c5ad854c387b79480f758a3932967a40f755c1d58c46318adc7c1c0e4e7e938991d5bc657055c42763e25a20d349ce24cd7ea9ccac7d2a02f08336636919be9fdda2e9acc571da8acf9de2dd9bea91284f7d57740ebb59f354cebe9ff76264ede7c16e2c7e986d50d660a463c94becce7670970ab3c9eb3c863dab50c94590a571b4cf7c3f9876ba8f352aae7f5e5310c40dc724ca00f763ea45b37d5a22f5883bf9808feae7bd41271c7d69051720e189c218e8f69c4ae8c419d57333efb973dd81fdf462805e08882fbad49fdaef7275c77896300839590ac217c397e220a71cd756fc25fd8faef7c95ee540769373f35ed779aecfe67947e8f80bbccf5076539e54cf130aed17f4ef0f9c4341a4a8473ed36b3c570384ac7762fcb791999b0cbfb2ed1e4685a474da5e3be7bede404cb64fbcc8c24dda02d8c4848962ba2c3281541976db046d6c84be6b6474d7dadd2f2be22d26b3c6f6d7f00a621081543fca0215f62145b8a0f2191bc46b80f37dd97fb4bb5acc45472e52c988c9667ea5f0cca0ae26c3483f704cf5e0ff2c15b0699ae609dcb166aa3a12be3a63aaad651805cefea91030c097a889fd487b7436b2848fd15a79dd050458dd3af51e664c9d1fc54e9fa3fe24153615322f865177226c1f68103a9a42593bae3bc0ffd3f633cbd6d730ec7f05156b4360f98711ac7ba0b2b72c461fb2356854c8f0cc54eb13819e24cdee71c1ed9536bd8ae0e7106ac3ede59cf801ee462356eea9b034b072a9952257a6908e834494da577ad926956fd77fd6caaa730c8f36241c003c2f74dfd04570df943ba90851cfbcaa2da9aff25298e6b1bf151e949ccbb4603bd354c206651e3d954ecb0df0e84c6e8b01019384be2273c19eabe90f5bebcceaf05e8c9b0cf3a945ef368e030501d55b71508182f3bb0782492dc041d9f4b5be7e07bdeb237e06876b294a5fc94fe3dc711f9d48bc7663ea8224cf5f8e2e727a7b2cd25e8797f629ba38a3e45f1a868ef07025bed386dcafaf75f54c5aa29237cfe0a98758d2980ce0d0459e4cde6f9aafb026d3033e8ec1f9ceb712b601d1e709a2051e0dc5290f6f7220c5dec8cbf0023057e0a00662d4b4e257502f0798dce85342b8d638f8e8af9b416e8acb0baac4f87da80aab7d4b887c2c18aa99ec6e006c0914f11c80d60083b51e8dbaf94a6cb0622c8a2ad67f7487f66a3a930d71e16e885bf2e388dc06d0ab4513c713d77bb07a45ee9d230b4b9a2b1a700dfb311a73e757331a76f4b550b83a83a66238612428899972ac76095145f89814a90557d9b5a3c7143307ec1a45d5e5a9631217c57666b29ede11e45cf44c21ba8c6a7eb74951f889cddce348236583a529b1f19774f5f837d5479ba8d6dec8d780a91a6cb78b5eb5948d6acef70f9e3fb5cabf4340b8fbc3a485d8fc9038c9bfb8e9764180d86adaaecbca8c08be3f5624d55955fe2f76838f4bb3e5d34efda0c37049236c254f723d72d208b4fcf0cfec664801be9ef6ea8e346e98a9b9bc2c4a5b6596c5d9f517383d617c7fdefd2f377693b9d50206354449588a9b0243dbdf797a8ba8e8124f6873a3b0dce1fc000000000000000000000000000000000000000000060e161c24282d36", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 54, - "comment": "z_max below the limit", - "msg": "b401000000000000000000000000000000000000000000000000000000000000", - "sig": "6971ace357225fdbfb887492c0975ba1851e761c68d797ef49e1499db3c593c547d77e01b5cc10e6098233169822d7060dfa32d18c89543f4d2278717107afbbe31ae12478d71a4311e3572ac12e1082eaa9b137ef48dc1cd7a4f1cd29a46b585593930bfb58be7ea877d879e5d5d6b34316ebfa8fc9506b1d0dcca40882599724fb316aba7f3a9591fd1568f404a5bbd73fb7ea2da39ab9720870ad567a5e3980dba137cfc80f5e078e41223e5643a99403b1f968463d3d9b42b517bbbd4fc91ab91bcd47f25b7a43df6cd948eadfbf05bdb0fd4f7ea06abf39ea358bc6baab19cc6b4ce209c7095bffcf21f7222ece48f57c71b5f458e3e09ea5a31f62be71caf283cca897896a5e90c7b39f6079105cc9aed1655220070525c7afd33b751755e879563c647b9e6c988474be81eb598adea6aec6e1cb90c288008d7c22669d1394d029ac985c4ee723c7ba6c98a38ffd199a1ce4871aa2cf58f9f317df8dbca9cbe7e7dacd0e542fdb1eb6153a13fcde6099b007b570846199a6a5df72155d1a58a38ac099bbab30e708cf2bf6dd3613fb00b58638bad91a963ce79566782709f3306eca323156713c89c3982ecb750182f934ee252d6183cb59728af83a900bce51fd582f4b5203957845517356094689ffab277adfeea87d381b12921c02c0919877db855553cbc73a0f85ded900f92fcd3c9ec4ae0c0176456f905d1c6d7d9612a5f302f4a9dc4c535d1ea92b266f59852415d25ab5f453a43eaee9575e800ae55158bc05f676fb4d2c02c7c41388654a5b943e85b97967d7935779b1022bb7ff292487ebcdfd8e3b52724131bda6b6612babf7b2d39df092dc40d47a8dff1021f5d79e71f5b2d43ea6124d44478a10fc263f332fd02d7a61d6e210cf91408bcdb10bf30964d047e71199a96ae927c8fc037f4856d357aa79312a3083b501f96da2ca704f477220f0e87b3c573f1d148def00451070544382d574c440e1d719ff798557b7d8ae5554a8cac4369daba79bc7397123426d9c3ec963edfac631fb69a79f4bd196a80ff78d62199dc867616879b4008687727178a47a81d7948123dba37c4991f7ae990d12f036d056153af259aff960876ba89aeb73de07ca7ee63f007889dfff244a2045a83b87a34fe3859454c6db7b3b5f90717dec1f61526b6d6ccff6f35b17e1db77ce69cab7a9709c5704c0b7e5aea9820e291ea524764feb0967ccba8a1d3d2d18eb4c80febe88ddeb6825294c26083c4fc125a20709f5eafccc485fecaf23d246edfc81ce62423bfc7588dbbe61432f537c159f2fd6b2ecbf9179b13f696a17def2dccb25b2eea4356d16e46e498695ca94722702f463769119eecc09609c93807f9f0bc06e3f53c901a0635398285522943a36a8f63f851ceeae361c067fa79e11daa28d3b5262f8e439b91e150a4491ec74a6e88753e756ceafb7a39408f560e243c67bdbf9aecd9e57fbadd582912fc82ac8f1aa74c7d0c9d57ffc79d3f261664b4e99a9d40b6c527398b42e4c57f84b002d58af12740d6aa1753875129158d80de167dadbbf335826eff922fc6f52447cc59a1d894449bd2f375207e31cd3ad28e48ca089afc49adfce7b27de1a058c8481732d17b93f25244563023cfedadb34e164843bb0ea40073e41d3b0fefff5175409bf49f5fa108bb6d067f058574d0f42150683647f2de84877e45f33c3ed08a383e067e2f79fea9e9c3a41f79d74d05fae2bf60b6d62f4da6f81391af155098f8fe83c062695137083eb4541b2e115e1f5563325e1c7e611aa435b4eb13482234d93d9c94077e83a073caf11d7a41292d9f55728f540b03fd64992ef952fd67af40a3de48dcf28f8460fea3bf5e1a1645ed2b22acfc9ea7abfc94823c1be154f8dc6ef8aec16f422dcdf47b3346b349b327303a8d73fe188c5d266dd8a5ab0e65d36c6633d1164e1556fa1cd5cfbc41cd0b9266b522529f411fbe3677ba6e415e47b820a201cf8011a2c889aff9544a0e51fcf3fb6ce8651179916010aed94122cb54301641c9bfedcad07d8df0976d835b59cc09b56c73ad51e6e0cb6be7d9c5444bf998e07fc006d0c6d7ca83a8e1df95333e2114c3ba3ceb94c0bfd93d223b5c4443e81893636beba870e9e5014160138a69946bfda8cc18cf02a1a174e099b0fb6331daf5dd9ca9b91e7133e130e1545a1f3e15e7335cff72d426d517b7390f84bfae7e5cff9ba3df772ddafcf1ed2d2d8a1ee15958449c9f963a48000a8e01bd042e8bb21261fb1d28f9c734d707a2904a4501afb649c41473c57831fe20b4669ffe6125d8ef84e1ffb67c8c9d171216c48a2c6be8e910a2e890d60c5fa7d8b09f56617b9ab11f9a2458212b8adf5efcda81d5b4f1c7350c3055bd2de75e02fe3337a8b9c1f6131bc78c5266c745e949472ddad4c085988fa24393e3094e1169ea5887875cfa95c21ef9a5f6e97d28e23e5a2674504893379299f57c85c4e2833fbb03c19cfa23b1100445292fb31e4220bc15257dc8345a17ae6078fb7f340cff74df7d483e6274e06b8593380113f64140dfb0084ef023a17b9a1550968a7b431cefb9f4d08f408b6d6092ba3369a1b093a78a7ff1996dacc2ef720e512a167d8f83139f805c9307523760566b59a62d3d36f6beb38668c4a30ab36fb99ee01007a0d3095591a3ecbbb7d6b52ea0a8faceccf8a4de0f94799e9d641fd07d55a0f49b35d58d4fcb212531e730ec4029658304f57ca077d9b65cacbb0c3e564ef119f59b56bea3c10e19aef78bcc5fbddb59dc2553494e9eb67fc40b438ed3be4c5105aea55c73ee843da95879fb0c496a4ca8480923ae3f482c2eafe9e4446ac6076f88f32b3bc976c0104703b63237969692f24da614e222af1454a120ad9af6b281961941988137b5f3c225a50e60da6babc6c4766391f1aa2a40b30ed855337d39ef92bbb07a31b07e562b429785aafca1940d70f4cebcec02ff2b73b4c1de24e9b1adbf5f09c3eb049a627ba7a7c1ac38a9960623fc1b30e8ce8e7bb276c1ec4004ddeff166d43b90b6444720d1b48998f10725bccd2d8b7f5558a5adcfde756d232e878920d3ec3de1321dd9b8fa6f653cfd396d0072a6fbb0bc339f9e1760a88d445881bdd3bb990285005e347c0d8f99a428d87c6f0551d2a5ad40a962ecc7584384333c1ae38fab091565dcc1c7019e8f6009d8c6b4166a2c1f2388ad8b8760d3b45af0de69a4039efee5b73fe2e396d7be843b49e28380a2782c9b5edc6229122d8823a631beabdcbfe6dcec3b45e26b4cf5e87ff3ce3301523e81f59641d3bbf298128eced2ce080334476053c13a460188dcac52852143327412e55a735329e8ca1c676461607a94f898e7acc8d6fde6571746387f556633dc8a0eccd262bc0c81b2bb68ba51519ea7dabfc26c234e78898188ce496e4cf4d879b0dfbcd032cd6f0e21b60635a167a2e6bb08ac56c7fa2b2ffd50e209a8493c561e3d57c60c1133c5ed4d8deb4135844d924fee38e7cd659c40646ecb52aaaa41a8de2c87ef6f622fe442a39a536827c267de4365ba8d7e5cfe5b48cca029023081522883c2eb8cdbda3eb702bcd0ab83850ccacc1f25dc3e5facfc3241b5b92e758756206149bd2c5be61a0a49153c98d494114242f40a24aa791299e2aeedb25693183dfa0a7c702cbe147b5e88d731fcd2ed5c9af78fddff0b5aa6a3b275d620de5875fa822353037aea429f0930f75d1d8dfb9fa541c2d544f28dc7fa84091b7d051179d5d61729176ce1c4c1d6018be6f65f254f5578b4a9aba5f54fd176757c8c0184288384f338b556f9b50f1f095fe840d06264224bfe092751388b43770781278b9ffbe11a6adb557aa2e6b731133499ab950861e3ac4896b4a7dfe7232eee775d7f3e93bebd46d863684006df058957eec3d56242ab1b048ad8a103d393905f93bbd3463b8e1e04af1b76cc79d6a622d4d3e052d994a7945823043845b51ad6565163f453b6c49404111f813772102e9d8d932afca413226e7bbedee794b14c21baac1d59534645a2dc99acbd22180f60118c3a907f7e80e8f3bf165a06754b7bce9bcddfc4b0abbc039dce743d5f7d01f68b17d63b8273934a4f3ba0643824562fb93a7c99219d818eaf3b85752c4b5f21cafdae54de3116b53b2d50306ebd24b4a97edb17ba95c0fd867e1b951d8fa98217e8d03d45266433cf7877a01bf3d0fb60e0f81e13104efd7b3a5470273c0cb238d2fbc2bd8db14de4e9af0d2fcdb80eb865bff7d1bf31c98b924738a8b213471acc813822709071c85d18b99d817d27c5f040d0d24bdb617557be380786a83ee575e0b15b3e7cdab6f95800b089832acf58a808a7b1e577e877900707cbbb1352e76a234b8a65b864944675d2349e7297980f3551fbb7b5815f03931f7f2647bcfa6111ed758d7cd90a019d71670d94a045ad03ac6f9c95565b55cdde8548b7af2df095cdb52c1c8b68992cdd2e4e4e490a49b5564fa3cb61c5ad3dc909e851a4d73aacb8cf3398d975cdcbccb2d9236031b5df571e77aba75ce8955610a0174ccf2c38a18ca6b6eb3e5e44b56536eba098f54c70ddffbc295267f66a3d99d2d58a8b7b26a831e3abfa05cd87183154900c7915f0bc38ecddb5d2ca9c2ce173909dafbfb03570e6e54d40bc0fcd74a180e8cb87e0a5647d02cb2680e8af721e8fc81bb23aa3bd6b00885cbf1529f8d0de23b31bf762e9128cc96ff9ea4a92064ac865899ea936787d8885ee474b627b99d14a7adfc8bd5b24ef6dcc1573cc382a0d4fb19ee6d92df1c41d1712d2e70068827c4511be1a3ed5b6d9ca0aa0b4b4eece91f97fda47085c4bdfa8636a8f8a89a30e7f37d59a9fce5225b804701201c2f472308a3ed22cd6adc96aa5b403c7b026377131e3ec2d19532c46d3f9ed2bc98193987f6870d825125ec16047a37c35d36a3b26c9bc65909f7cc97fa1da070ff8a3319631f7dce6b40d91bae06ba9a4e88b87c7381ecfd82bd007b54cb70912de319a46512eb7b2c941aa2b616b60caaca71b64022b2ce60ec99c57430fb03a16875d5bc70b72c8dfc65946ab08f611ab8a75b64e4f3650da84f2f9c825c3364afdbe17dc5f637d3174cc40d2debd0bf5a1202f84f17c08f64cd5c90f525337f880415de8f8d9fc6dee0506cf1cb70860df14bf5624e83a57c923ab1903641346da6362391cc2082d63c277911cdb4184ef367813d15c22e239f811c6a13b1c90dfc36d4f2cf0ee03ca7b4e8c9cb64b2a4d69e094f0594f454f5c39226e8d73a7d6f7c4d09541b675e694296d26b0b9262119c69eee2ae3301ffa2047af5d137f86fd6e117b8fe0e78ee640db4a18558e4fc7dba98f5a2086a2bbc716e36554451d06d715c39d8bed744466b25c4510d4b6f3fc1ea030c664200fe9078124089e5f95601a20c5c2961398a7156fbb686a5c7b75595927773bf14012051047d20780eef5a446bd0e62b306f8ad3dc3fa760c64dd4a67282c6defc9c07bfea4b2d409465f978743a9ffd043c5203d4baa147487c9b84875e9b6101210bf9f285552a29aa1a526ec1bfd34077091889a757e5efb9245e35599b3adaa3f4002fc101a11cec901b6338482e1979eb8cf4112e5696e5a34d21d228ca62728320b72e54d1e811084f72e2656ed8ec5628de365669c516e7bc56f81ff1580c0850008f537d0f65ab874993647c70abcd72e7cc0f5c4ba46e059f49b06541e46a70d5c0753bb957209430cd4b0aa1188a0bac0d3688fdccdb6314b1f61d3eecb818dd9fae59710b0e171d89063b5b39f596014d488cb2880a304481e2af8783c5af30ac155002ff74a85c1800bfc1d5b03cb177f54862650739c96dc2a91d48cb5586e407fc667883cefd39534e575857004f9041e3d1379986f6cf6bc3228ee8e6b62af0b44ef64ae6418dca1f6a78131cd51010573136fbe8911050ef643a6bdf4b2cce8db4acd6b58a06bbadbe311e67e8645baf7eb58e5dc31dac8ef117c8f69f33016461e44cc99aa7d3cd7b428c511607aeca9b640e4a25475388a618cfdb68d6e02d644d870fddc3d800233ce948130c69f884703e4ac67047615227edc7b2952f7377edc2ca57e184687f47f7c026e766c6719203e0caab27b061c62bd7507f4bc9dcd863eebe0caa70b2e36b1c0d690d28fefbe1e527e811d549dfa908c3ee590e932584d0791096b2e0cb1ffdae5b5eb031032adfe75278c94c0aa0b168ddc00d57504eb7f7006b2b7c11e8d3baeafc08ddb71cfeedf70f2662f8f7a2d962dfa12b7a1543ca35f6ceb54198e3d42b4e51d8fa4d5915d241d574615ab3e5c3940213fe0c15e58b2e0b44c85b8c6b435e98095834f84a305afefd1bb85a867a86c70cc3e9a7e57a848e32c370b00f306b2fe909e16186fe3a7a0940e0139d6af87db12fd1025606090d133b72c1d8ea0914707f9ecdec1c396886889babb8dce0144a4b6a7a90bbc5d9e0282a515a6065688fa9b3f1f800283d798baab5d0071742596f9cb6b9e6f2f51e2f91ae0000000000080f19232f374246", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 55, - "comment": "z_max above the limit", - "msg": "0300000000000000000000000000000000000000000000000000000000000000", - "sig": "4f05ebe543bc390942447d1dbe184fab96b14d92cc1f096092026f2a535a3c7e92b4d198f65be958e7da21797b68aad233a59fa05ecc76e22974272aa9862e92aa4f3bc7c1695c510169f6177a574c798a4308a9055b0df966b15fd75f9de02fe4290d50ed814244764579fb9fc6c50459a92c70daf58574086feeb2c24f290b7ba99bd7c5198a018d157fb21ba42e83d2ded7ae6eaa2cb09866cdc83f666e09983aff29b8fa531a008eabd84b755a3052004e3bca4477650c48cc46f76fae4a982675148bb26b4e8842989af547d8d394755b3cb61d4a1672ba9b47bf5b65553fa358c1d042928ed7e5e66c71dbcfd611ff2c55879da2c5f96256f9781301befbeb8f94f1bd1314808cdaf11c93c138ab777d8ba038c7f7cc72f1cbed2ba299732299cd87f35bfef8e816bbce3860f8ea529f7066360952de182a8639993285db44b5cc5db2156d6c9296757711c0c0e989693a625b8689163d4e3d3d60892888185279ca0ee4760472553b74d23b6afc9cdf10f180d62081e68052daffadff5ccb9c14f2f5f9725b21a593b83f2f461bbc1edfcaabd20a5e1b6561d304b2531f0d0a98741662ef8ee2e16943ff6c10eb23c228e7d0fdbe026a07bc4a8d933e08b9d092cb6bc88cac343d93f3126dcec3f0f8ab118618c16c0fb3c95f07f7f6f4c98752b2bd60c583ece4dbf247f466cd9c47a9848429b9302482d5b9e41dd5450a9d9c0ce7483fb04baf196db75b258eb4bfaa5c3008a419bed93bf8d914e10d8210dc47e4804adc8131ea62bacf407eda0cb0636b69c96ab4ffb66953e0a3a86e826f2b874774c938af5cdfe0efaee113cfd986749422780b6756b8f401bd216d645d5e9aa71ae39d4f725922625a58a784a133aa32727026d270d54271bb26bc6e73965f0587190262c58c5dd35a932594fe6cf4e77df95b540259e4e41577689db7b1fd12222908ef10eb46d78b1fff4e3720265cbe4d2147341342593042f171c8dd4b081a95e4ba44d124e681f660e853b54b2d10b4d809e5ceaadfa365caba753702aeae196fbe16350099807d1b71fea2dce691747e66ae817c1b2cf5e3c52cd461d00179411cc9f63eea93b02b2e9d0077f6bbc046f8e62f35283a706c33c5de723c6bdbdec4ef06f81ecda49cb0acf4f556305e9d5d1ef3a9cf4c45ef9c18615bf22ffee9d9b572ecf05815c09293a4eb14bfcca121fff08bf0f2bfeb7ae8a80aca29145f27cdecee45ef1adcf1d8aad1ef1e8877d4489fceaccd6565fe43933ac12ff5b04f89c0767fc53d9e53750bb6234898ac6b534553b946e10f9e0b0bc6443bd46b92163666213a065e7d781551dddc78d53612e000ad167ab2c3a217335fec14d82ba6ef7339e2ec9297ee17a1fceb85be2d558c33c569a61af447ae5aac261fc491c928160a092fd28748959878535ebafed74f78ff2fe44c2a0f4a4a791df80b9f98774ac148e19f3a39cccafa1b8a27eb24307f1949a115fba67be21bb17dba8353d9276fce0a5cdc4b902737db76ce109cf001c812f6460e319254188f09a663c2c4e8c2a66439f1c6cd208f8d581097f66b193e7e094ed9f81682a05f13b3d5f686db3a546abed7f81b9299c852af75af452ec465aeeef9467c0954a400600d1f47b702cd2b961f2746b2418f967e34f56d73065b6bfb27b6986aa01a5ba9d37737d884d254a5835fb56a25317ec8d0774a36d2354fbfee1eb58f656f05d49f9c7706067ff8de4f7a0d5f9bce3dc24e18b3368e9ff31b1a8fe8b96e05990a5398f28f307408d3216fb73b281db8a96c56ece65e8702a2b725705cee64c83d6cdde26ec562f2398a9178c0e3fb4186894d8120e0c9eac27c90548b7a220a24c7fe725ce956cad944feb8d6e310e01b58eeb29f3e8d2ac77b922ebdee625a9349432a97a749bc8de2138d1e353089972920e2dd505b2f050b154b2871375d8c0c5644bee8695e071829341145a57e35bfc6a703d452cc05070222f525ae6bd1c31597dcf8c60ddee4c24029781273e136f8c111107c586e523fed7eaf10b6d697fef5b60bb921be53bd33a50d9e1f082eaaea7afd6c4a372e720d092a85b4c824b2ecfeb37b1304ad4de2b89e6e57f1d03586ce328592850f793174b81e3e5a3eba483907160106f75f56ec6e3a9dc0fb5c737710b2757b77e581f25687b4bfd4393d6e1d93045815bae692c794c4c7d641f9a63f9a1dc001c3c23e48b276ba957026aa77f8ebe636df1083e88d5124f5adc6ab96a7eb76f8fda454867f7dec7b19ea52f1a9de5a4f1710960f4d991fd2593df95fc5805754c4f26d1ec55202b30eeff6801d17022fe4feaebf062218d0d23d2e21878edd1086b8c15c6c4bde37dd51e950fe4532ddfa1462651473ecd36d1b11baf32f3631b07c32e1dae061d5b6218a43df9a9c8b0de5d6b3bf1d45d796dd85091a7d67fdac72016a911bcf65db6590334144a9adebff5428f3ad6d11f5c9e470244a15e5d4ef602eb7c514b603934ccd6b89b39eaf44f3210df1e276ba0d345eb77ce2e23096177464080b0a30c7c35dbdbe7bbad66699cb31cc5a8ef2797bdbe193af65ac28a083038d291feca3ef01859357fcd33a09c571d6ffbcca6d0d7a34c1c6690e926c89c29b8bdf5bb35c5086d45a485b52fa45eb8ac011b12f2c07b80230aceee0edb3c8b7f739998e25472438ce90f97ee691bef878c9e943801a845abe3653300b7112e7c8e8c47a666b4c853c3e6a8d972cec32746a77e69e2dcefb60619f77c6311d5360737893c5ded1d39b0335a75be8ce82ffd68572f9800f44d2066a4ff31f47d831a0dd740f94871795112becf6326ecb0212e682da81dd24aefac14fdaaf79328d4a1db1e8f8e32886bcc28bcee0906dea4e609e3294a82710f84a65f8a3347081ab162ade3d9feb4389d5633cf0a11c25dd921ebbe44e41e316c59bfe2d85fe11f47499982027b275ae6064794421c27bc48956124cd59125573e0922586b9d7b45410d59b69aeac0616b45d4c926207a351dd47b538453f62833f72caf989909590f974725bb8d6b28d0a2f2849c9b67490431f2369bbd9c82e952b2f52d10a394597357abb0ae2dc362aced8dbb7c656009392f49e3dc4b39b69ec0636cebd80dbfda14a13f1ff0a667665ce06c7cef2cf7b6fb76d559dff4b4c9bfc7342a368846c696055b04852172a84c34709919b20d7d1c26ca9c5a0078adf4140a308c9854d3db58d3f754cecd19eb38175c622f315bd4b06fbe95ef58fc285bfc32c8c7c3eb108d9c2a1414cf0fa7c29f3f0aba4dea7f0d52aeb6801884daa7110426afe86b92d5a6ea6434efb5e4a3426188cdc4d7abe93165f759d2c1e133c2300e8723a4838f00f7b767dfd46a833dbb18f11e6c6f46dc60bda9a0ddc542d88dcd6141fb5bd6288d444c668b11ef0d5060a684e76665dd920b6b62f8aaaef2577773be5b8b1b0a6bdd020be3d90ddad1923c73ece562104aa1ba190714d89e390c1d862b4639d20805e72796d5ca5cf3acb3d1e1482c91ede1fafa3de0a17aa3fc2aebe7d548a754ddc21b2c20bb1edaede1f7d9135b341248560d20ad062aff33bf7cc805fb965615df40b8888a16e0010c3ea374a5bf854954ce2aa970a78a477ce877e1476ee7e9bcf4c053d436cf8cfe4a19ed11c0f85b110e68a6bc9d0dad3ce5fdfa4b70b7647fadec9fdff273d29a8b984792ca069546c1a30edbefadddfb507b106b3e2980909fecde27ef544be67d8f110375a3b7e83e8e743f58b8ee59f379314b3982dce9e055581a5a58dd89320be4d8f70306b6f14c0105872e1f68c2a758ec2b77845d34df375dd32ab5302ec4e497eeb58e11cd4878f583a2e98b27e4cab411e25b9c7152bb8b4adb09b6a993161cbfaf66334b59391927e5f39174dd1661495a6b702fa51050e5df41570e1ea5d773fc3827949aca9c3d625a616b700664e91cd6599dd40c19f8eb4c2023422aa6d87f3d1a75696b6f6430c602ccfae5963e57bc9abf36ecdf6e51c938b60589ada1bc1d40717717694d0123740eaf23c47197b6408c3be82d120bedb199b499f3ca34b180622a86431f1979059fc1f41ad7a3b3da1eee015f59bee059ebaad20f194273bae59e41c1f3476f4e15b74d2600832b9474d64bc716c7f152660c80297997d0b53f9dc962a9bf5633efd8cfcbaf32703ae121b0ba85d1e67efaf708c5cc3f2cbaf6119c41044dd1469933a9b94aebf82e2f97e854211745daa750e46934a4585b4c86d531b572b459dae2dc3c2631a1ed5de6a7ca1f7da7ee4cbb9f198b9eb965cf556a899b4c770bf46ce17ede41b5c897e67733954913fb83f9d88e10504fa858433df6fe3197bc9dae7a960d2cff6b7e67467788288253df8bcef61698fe54ab860f63a8b91b238ff904a579d53b57ae887a09c99d6904d3d1fe02a54149235e1a4d562ac008b607ddd0137480634bf2091f6c87f9f4073522c0ab43552df29ad21db0bfd6a3445505196af559fd6642e1297e0ccb20d6c34611265a06f9282738ec6cacbb73f00f3465e584d48aada9d40da8b9c84d1211cbe94a4b0eaa2aab07609585a4b486a5b116a649e5417b299e609e5e085a5b0a91797545cc9df523e55f3600891f36536bbaaa258df68662a43a5935a4dcf0c9b9fcf47cf296150795457a6b7bc820dc14929a81088ddfece65b33696f666af613e1ddc21c79499fb0253fcb35c7dbd7590818cea8a0f395bb79da2b46d3685edaf43cc6c5bde5884d46bd78f4e75eb315096d9f603b49f7507941abb3ae92cc7ca3854b38e3f5ac5af4782a2ab8949fd7e705e33cc652286fcd3c3d6b37b0db52941dda3244d7fe5ec571782976fed7088dc45f87227442db882a8cae944dab1775cbb33e6ba26a09b831d33e4b01357a41e2aecb73bc543148bfb659ce4716cbb8fa246cc583cb045390162f07fd7771a3026894cfa30f3cc2c61fb69fda2afeb20f034637c94976177fb5e35a7b3d8d3fb62ed2a3a5a4914cfbea446bedf93cb332fa38ca09862651c3416e8b646628e331bebb4ae8e4d5b965f393f9665ca82429fb2034da62049759c6c47a977a3cdff7faafdef74e4793a985d5d40e33e164366ba4070ac3967e231cc5102d08d4f68e9e3fce936fd82b7329c23d273e169224e891a0b058d61496688233b740aed515178c4444539927711699366d97e0a01d80ea6a099ce7212b3c7836c601b87ed5bb72a0a4a4c10ea0ccc7b3564f6623d42a83557846c3d23e75afa5bb4da6f3b71f522e9426d3be36786bd0a8583e1e70fd483736de1cb7730a20b1bf2a6f652bc85ab128368bb588c54812082ce8bcc8c982ed592b4c5f764986b249236f184b885cb4636efa57fff8a0811d611cf1e129f047acb841462111c8e65162bad03eafe85425212bb46321ab3e8e0a1b507dd5aef11a4f5875ed33e027615faf36ab09a12093cb43df8fbc5528c988fc4e1fb7d31dc8584a41f75096b1eb015eaa3b780d62dea11bd166bf8bf2af5ad1bb3bfbe178cf91edd9edd32a9976e3b085ed115d97b3db3816993679e4e7cae55914e4f4ac576bec628ffdb26213ff8a8205046fc91e042e803a88c70b14429c2f7efbe3df858dbf497413a84be372bd58b19e8f3c30a73747e2c8e1cd56c81a25f1e36f914c8c87d565bd6c369ee2bc4dc99fa0984270c5d4cdc0368e330e37028b43e59d2441462bfe3adba3999906bb0c5c3f5c1a55c689a8575c2acc5e443298f23a8a3d5f666540f77e4ca25c399a9f34878413ef03643b74f84f4553c76a7b253f5f9939b0410e899acc9013d0b799ae4e2962de2f35fbf1058a654c7d03f011a3ac3855940f1f060cc239970b3bd7d94d7371eafc1b3c05b98706828f20c98e0f1dde697652d0670d1de1ee48db07522ff1b8f5f53089e6fa2c5cf62872f202bd2d14882a0c24f2fe3e2605ba785d1b2c2b0230ab2f7e070eb6e82343cf9f1094c6240094d846fc5cc4bbb561ce4d27e8771148e19d8bf858767f3c262b4ceead4ccaeee7f2933bc888d2e00a6cab1cbc5bca6c132c1d221add24369f8b8ca903c50aee9922aa3e2d17d1f9b62025d338a5131fa6c0e351c309b0f503d7d48829fb04945b5474bf39103a3761f4e85eefea521d027c01fe0371a9ee1b8a128021bb7b5944580d8a05f4ebf1f65cf47a6e8923555f7bbf22eaf8eba7ec1210a32a411c7cc68b07bb3dc29f89035239ae24147300b50a6ecc37349097ffa16a03bd51fd40918175807a02aa9c41df0842f8b536c9ae843b05135cffa16126201e0db76a1aca2e05171a5f3104f723c4890e121377fb716ca40cbd82595854f1a244b4ed47e1053a79c344f79e766493d7a4db8810c67653db3581775af98a8fdb8beb50e866baa6e66bcfe188601fa3d25932eeebdfd3c00f1619b2e850c92d589bbbc49199d1e815424380c0f5f93f647275afb6d9ef00295871a9f848b4c9d7dd3b7577a0aac6d2e0e8050e324a9aa1e8000000000000000000000000000000000000000000000000000003070e161c212a31", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 56, - "comment": "r0_max below the limit", - "msg": "1100000000000000000000000000000000000000000000000000000000000000", - "sig": "19ae6a59256e6fbd0771373e7a58708947ceb8122747527ac7fa697c0a11b4bd3b85d4601c4a755222e80c56809b2cfb3e07bea21ae7ab71f9a08808215ecee8f3e0385d6287ecd26430f2d314c16073fab6b609b9aa782c937425d85a5e8a40076a99c6943d9d763991189f2ecb5e6ebba238c4f33ed98655d99f837c5f380f998846c05866e8ea2d49ab8710ae4a00bead4e82dfdadd937f64f3eb68f73f30c7f9e0af1b2101c50e847413da48d3531bc27187a622a032b0c2cc004cf8964bdaa9236386976088d402f2c19a7694be2eb22eacc3c0878a9a6ac67ac105b0f18388c5629d6d2f15ab66818ec915e3cd21a0835b47d2d1c79d75e986bb6121f930c95e74b549e1dc1019a1eea99d73afca3677cb31a276907af768bfbe4f5bea7e5d7e2dd5f98b1d7f700e030c27cff0d65d224c2f5c84a593223bd090e9a87ebb35e5230292d2d83d40bedd8199c569a851eb0e7bfbd1ec41f5a82f5f46b4e8f939aeffaee84bc3b65bcbd1fc048e017be8e6a94ff2a17336636c5eec2fe30b1007e9801ae562f3220117d918d0000497ec00323c783f3eae8134e3cf29e5493eef07650306e6f6398e46b424d7c19ac3b39705ded999705d93f1effd324266c7229bfd11262ce1f40cdc07c56376189b775a3f53065e19fd34d2d8732d94813c62fdc646c854e15269fc0377351fbd3f4b0fc7de5058d0d2ee7e3057370017fef2c51494a1032dd72ee93aa3a4d3e6a96e37a2cd918d78ff499178e3aaad85dcb1505e1339f103df5da94cb78aa204f0a67af0cc81ad462c6818352b8bd1b8ee5b76db9cd1ae400c5c2b04caf353ca5382c72d872098209c36cefb171169f18b64bd3b91dc7c360f068b1295d84a259b638e526e02c6fce3b71fda3cd389105038dc3ef0220230c42f008bad41b42a66cfb80a394a697b474ccc03cb6becb27d34cc5248f3a97c58b0b74bdc8f29acca5761020b4d802a2f89232411615b616d9921fefcc64f0d0fbf37d74390d1a4c477e930c9a4260096dcb831f524736c401a0d86c7189ab169fd82cfafd0fe809ad8eb68a6ca7a2296a1cc5d1d950add54577374cd790ec0213aa6f5c0c54ba53e22deb34ca320c3634edbbae2663d7c7099f8af277aa444e19a55fb3a6d343416a39e5f292af1ac3e61b3f8ed66bb99c51c20b7a70753b3f676b6f05c9671bb5eb49bc531d60efdc7266c1aaa8cdd26f1a12fab3a732a8d8bfa96251e2eb8737041079b5cf5ae46a22ad070b8ade304a3c10a8eb17fa20b5c37b1ebd69a105277ff7aa2fff53fc895f01a4c16ac4bc043731445d4f397a8af51545f2a6b7dd07432a9e7da5e250fd55336060ee91aef91ae64de1e7265bda62faa6d7d66af6a30b9e280b82dd54fd6b4025eb87e191c33b3c59cb8545cd91b2c7216c95398c56e430d80c30a5786bd3ea5b9cd560e8f4f1fde51160b308fa09f06631b563407abd72a5aa0e9433dc14b028337e4589da5082ff309a4f54f28897ea83dce9a7f00c11b460afc6b7f468c093057a91cad7debbaf4034d22d1033d64a6a53afa0950355b1fe75ea7e76359bdc9715618c637a795fbc5624b7ccef1bf2c456fdc59bebf529a46dddcbe05f94fe474fbe2f67a37d21e1bb3bf0ae5b1529b1474ff1c30effbde1829ce4c70f12e9ed8f6cba5e313f57689e249786573ae3fccfe836c99154074a3e25d84cc3472468efffe1bd19f27c2be739d9fac4f3b0eca9e0dc422164fa1de778c3e2e963af800feeeaa5777300905ee6b944f0738bd3ac70b07f07fd44d1237d20938be34053f2c0a6df8b8a30393fb6c8ce5fc9bb0f16183bd3b8cc2ac8f131901d7d6c5f977f9e00d2680cbddf58f53e69eefd7aff151c07059114eb1023aa7ddc8fc499d828e492407e3ada888dff688e9059cdc14f2c24682a8c08993015818a468c232294d60a635f39e1038ff589c3d5dca5f4e88517c81411d958c1ac41f32e20712335dfdc535eca3878b241a0cae45911d9795fe4129d73605831ea06b2a660e0bb8db8507db90724b8d43444ca9be1a09dc5850bf6245bf3d67494fc522f5b02a3b605f7f57ae30dd3553de395804138df9d4e618f5415941452a01e40c09cdf84d7f843767ecdee863b4bf5c60292dce9b017c3b1a9f30f5c3143fa78bd17038af67cb2ff1c98aa55c8b9cbc1901d27be5df4e926433fc0e01afd4b823541bffd88feaf94a028c7772355d0a64aa18e0f1d1b239a84244a3f5238774a7a259c4ecd2794615e54adf59cd38d2cb315262a22b85008093419dd22efbf27f06e14e1d50661dc05dd9c5074c71187094f2374d0140ea4623580f1c3c2f8677cedf77bae1c5a5b7cb1d2b23db343311cae4fd50f2424d298e0c236023f0b53b8709622a7f0305197fff2caab0dda080f392603c8ace6e46f7d1cd3ee7ef7f74372fc2028d3e550afdd2085078dd373f3a27fc2975917921f1d7ab796e8c77f703b1e7201a48ef5fddd465fe3ccd2465ede8049d54cc60d06fee0e5bbc2912a2d44e250e0819748c797a2a44b395d86fbc48979d6ac808b2791bc3b11312d4d312a46d835e5233fc471bd7b7a802713d2d1be5eb7ca8378b5c2c259f91721f6ab3e1a5828e7804f9742adc1b3dbf5a5367325960087e3976db60521ab0bf559aa43e5cfe6f354cde0020ce894acf4ec56db0bc8cf49f17fe0b5e00e147ad50736360ad39bf5c561a8570c5472da1384ecd3c698a9f4988986e68cf311150ba5926e56c0b133d25d58d6d741f7a764a453f370161bd258dd027eb9cd8f3a1aadfabaebdcf7776a85bd3ecf852eb6fd38fae45e9378637b6d61732a7b39619c2c5eb376387da563874cb172235c814593828b2f3ae8f1dbd51d27b73246acd8997827c9bc6a44364a3513a9e890fa0eddaaa2c69ae98934ced34d97866089f4481f02bb53009a3140fd3d3fff07dcc0907202c7b8c2491b046427e2278cb07cc61c50fcabbe3f34dbcd2ecc5ddc5139a1f99f077c04bfce74f1e25a28eebb1e1e4210c3bdf749387d02f1ea9781b71d2ab447c2c9eda39cf0c95b587d2083a683979106f6cb8dc9667c12078aafb97d65a349e9b4b8db4ccb291ce8de306b53d88a8919bbbbc2f245d03221b3f7791ce7e86997a90434b588d08b547bc30072e962dfb5458d2e47eeeb2c08f92fb3af636bd30dbbcd0133c7dc5a0ea56f1ff4566442ed974addc5b46e79b7801bafe7b70bb216ee5e85a8ff6cb4c96db1dde6f275a9273ac670fbd976530e0d4c760c4857f26998a4e2432d0f2fc419213bb0fd6ebc2c600dd027d7d0880aec2cb12516c53d3a322e353d683a0d0a95bf42820ccc4e2dfabb329ff7fa1da8493eba4e0e0f117a1c1e5b1000b63368edd6744bb352dadda8b79986c47641d500c826b5d9de721d7589b652bf4e085b977ff1494e1e3ee0c730c7fc2b9d9a3a290b63ceefc5bfbe47ddb9abd422da0b347e56be4f4385480955b292e272665b8e59bb697a30c5dbe7972e28088da493c81ecec7af931c72eeefa2d97f6f0a38ef4c2253b2a45971bcda5d2495d1194f3a44f7dba53bb93684ef7fcc47e11af588aeb7e8196dcd19cede976a4a69345c953eb2d349b2114582bf992cc275c764293082cd02554d82150a4aab3561d838f2e4185aa0541d6eeea34c690390e2995969ce77c4e3df335d349efc0744fc2f00188b26eb5374f40912c8abca7af30403795b04ecbba77865768f8bc74e3da3133b539c813b7de96b422acae5022944722f055d13416566e8bb6ae3e87306a4fd94179beb0796874f38c6f70f70cdf829e655f23f0783b37d4043551f5f2b7640d621c7e823a2f2752323065df7fd85f10693d0355ddaaacd21c147005f6152d553115f69f4e363cb1a918f25d097a8fa20b52bf73fe76bcdb0b8d47a4e90d3bc6c49aea17e86b3ed46fac9f3f010132c13355300fba6af903cd10bf6421001c285121a09e024c0b22f303570e64d9ee82eebd2256532ab1bbb97771d0e7b48362625179a1e76e8e32f02be52a99b1af215cab44d1c4c938d589f15c86a962f1b6c9ce63d6969b42b79c450f684c4e613101e6decaf43353aba3c3d06f14e20931a227bf4c329715274dc92fcb3a63a469556b632821ce0a56848235e727699baa4d34741c799355b8dd4b5d6b3b9bcb9e7f568f67964a582a3094d512228781c322fe58c55342c2838e4b99a067a60a0fe0e58f39935dafa0f3943f05439e0e9f5705c23385faf3a4a132602302ac3eb68473666fa16bba0219f56af2c02c1b634e6ff07c7d29fe1aabcd031592a39d64c579492d1fbaa18834024ef4b3d3bbf94bb51f4ff360d96f2477ef2f09577c1ffa466c79657cca2638fa627fa478595d52dcfec7e535aa9073530527b6041e4718275c4ac4653520ec18b9e726492db278a8460bb6cb3b5d1942b39da670f48829710c2fa5c6ce2d6c22be7ef3a92467ba228c9b1b4390603a640269287b583de09b68e5c4ccde813450755e332fc242ad428a1fa977011beda483c88d14acee94957c5102d8451dd4f488231b1653c79e6a0037fb931b1759824c1036b9a62fb69d65363e8070435f7b473bd75742138f771af622ec5604541f78a58fafc526d74debcf10843af616c188dcd1741ad33fc8af61b5ee5df15bd5596e5504e437fa57658610d6258e9d7bbb7b68bfb01965f52045a9823ee8c7c5207c6caccee4cf5b8a664b6bc80a4d9a31024472087960a8f7a17609eacef0ed404ed42f5f2ca0248155efaa8d92a8d3881fd7037ac9c7050beab52ce3ac04d84820c2d40ac1a4fcc0c2e53adf3b45ce5fcb0543a4ec14ade338cd410b08e873dd6c69a445229220690dc3ee6aa1008a42e95b5b04806cc149dae474059c14a4e4ee70fafac7e0f9e6a46eeb2406dc2db6804d473753465d92b5a512327a5390f6e9b6b9dc1cc7d26c2d874f6dd408f200b75d369b141869179286ff869ebbd6f0aeb4731f6f0fce75f3073a56eb2da03e5aa4e7919bf8a8e95aa0e739d4625b22017d0a959164d3c850ddc3747a87c1fba157147bb389f139576268ee66c3a68a37e44a3efa024e75601c9612c25292393c19eeb7117e992ebfffeb2d954e169ef13c793d4a1732b1c6c514203439f9e357608c9582a345a1ac7160e531906c932584603ae033ed762902e629985269170da62c4a0dcb942475e84f4795a4fe14eaebe6d81c8449b7be833538c2c48ba00121ff71baa112784775da3a97952204e7c36667b032d0653c7a1fe6c049c55f06ef6e7fb2d082245caafece7594640ccea08c41a3c8e0bcf6e9de3c9aee6783d5ed106c106fcfa661e908a6660c1703650eb3b0214ce947f1c3bb17c8b9156c1c40e192febd822a9ab1293426fc80ec117b1f8fde63ee0c22b743b4b4f334df749933ff182186bdaaa3274c0a20ee495d195a59c9bc437539d46aff19d5696e199e9128239e23a94715a4d9cbae6fcb8ddc7cd299b47b9b3861b1bacf703ff4a365548c9f32f5ba8c9e963ddc29415aa8c46b602436d35ea864ed77b5faccf0ce4c4ecf2b9b076a10b25bb9a6bf75eea8b5b38f6ed9ada84baf2267a5068964802c878270f7c1e306d01b9661889144fe799a49f17c857eb03487a4a26ff7bfa247dab3384fd78f3c6ef2c3b392e1dd950c332ac038b03b72da8df56e1676ade60cc9e188303a92e3eca0f4c4fd0f186b30504fe107cd80ada4aa3e3de3145e445e267412e9b5392a457d33f80f010f19f5dda7f3f454eb0e26d24d426a146259606b42fd9e2ebeef0dd8ed74692259ef869c72d9bcbca0ad16051083c0e7ea52a44e6746a278ff04e90f588fba34e812e7e7ef92e3561eda68835bd2c32c5171020f6f9aaa95cf5c94367ae5907e21a04079d637caa997145fc20a847bf36288b42af90817074111cc12084bbcb6abc3911b71ea5a6a2b7b3586ad0ab4eb5df7219ccd110363352cca2478cab48259693c5ccf3d8b5013eca415762984ffe1868817143dba4549f20abbda0a535e7924ff5538614b924bbbfdeb2e582d5fb99cc9bfcf8bd5cb5b9edd7b509370751c9528ae35152906c6003e136484ea1228c7bec816392c42137075d07ff34b7a01660aec8f1fbf2c4983636403161593999099952a214e5b48a5fce0572653e0ebc4b3c610bcecaa3b1247bb3dd079a4decfeffb28ff53049878fcca1071cdae4bb1aa43689a408072bb710e7a7caecae50d64341921d502aad2a8d44b8cdb9fa8d7d3d19196665493bb4e863b3d465a5e5028acde200750ec9e70cf8cd64c7904a75795ab0bfc609277e498ad9910843ee896b08772414da82bb92641a5f366c3fce337681660af8aacf531be95cdd007ac254fd4dd17cf97890c986afeb1574e2b7954796bb6a089b72aefd8678bbffa5413c7530c2ec532b197d9298a13365e3c5b86bbcbfb6266728190c2dddfeafb080e6a75add7e67f89f40b1e737ea4aecde0ee2029a119435a9094a4000000000000000000000000000000000000000000000000000000000000000610171a1c23262c", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 57, - "comment": "r0_max above the limit", - "msg": "3a00000000000000000000000000000000000000000000000000000000000000", - "sig": "32e60d8c723289035e9091ec75cf1d1c1bd438a12e3ad4f467d13166abd781641667063a342a1eacfeece6ca2f5164576d947c681ae4e2947929d3e8bcefa4c3e777fa79267221b0d7d78eb99a59d712c48d2fce4aea7941dbfc61abb91c6d163e73b8666dc7843d45e69e9478fb9daed932ea241fcaadeb7de1ebd282ef863690485fcfa2f7738dbc5e93eafbb818a66f69748eaa95209c0a76b5a8fae566b1d464388c65f2d31e376a9e6158eadcc0f1ae1a69efe0f2a219a82f48c63686ed15e9fa832aba08ac5a302430db0004688d3d6c74c9fd88ec364237d40dfb99e0da9614b64e1e7d591fced72cfe087ad293c909e5f370a9fe0da0b1d99db3dce3062704287add26545015dc1c6973246a795266d70c88e96b4b88b9223f2a0d687d46be4ece9c319fd7a033bd1f3ed964bfaf56b9b5d1b9fda100c0538c5147d8764714ffd1fa58fada1cc9c0e8006370a46d7c506490e645274920587168384c2388744592920d0ae336f86ce37fbc6fb7b1fc6fcf98de173af0bd0aa2df173fae18621bde2f0561a4652b16d5d098c2d1e09589f4f4428e93dd92e2d60971511da99face26eeb3cff768eb1d4e31329d45a0cef7654f73c3caf2d13aa9fcd0b33d76ffb332265b15ba97934b34563f2bcf644b599f4c982fa36aa8f14e33aa25689553789de2e24844c9337945ea7c71b61d49e40809e20b45e5985967ab5c2a6bc49c15fed9305d0461ae96d231e4dc775731594ec281cd9f92683efee4f1b3369a1501a882ba5d6370a93f67035c4e9d8fed0e3821cee2b966c7b6ff23c8a17b241ef44229c2e945ae691d1387cb2b2ce4d1d30b8883ff177858e82dbed28fd9055012039b18168cb7270bf46fdfcadf58ea707928d2abaaa0a9f26953eb6494ced730136411b5e5395894a79e16414c85af6d8e47ed4e5661c01db7a47dcaa7a76f85816fc27044751ce2625fdcc8290357b98cde4bd9d57e4b9eb3249dcfebdfab5f2180506e916000d7fa3e0a86a76c5a971b0013706b556e8ef27f729d56bd47d06ead6ffdf8c91a77b2fb857ff4e066cc113ae600c39632ec28dca2c10013c2b980ac8f874236a39ada711a3c0ea7710edc7007c197d8fb1ae364a12aa38c797b61849c76bfe0702782744075b32aae2539b06a9ce5914120e6b49e250b3dffd27f294c6e2237dcad5dc2b3cafefea28d323bbf67fb2a5b7753c98d3ec6aa08bcb14139efcfc8fa55cafee728610e4cd96d5efb746a7fa1ba3e8d4d40e836a883f6b00246ab798d3ffab59a3ebab70f6c3259b74016a54bbcbc4218257c1e7a7073d346c725e148280cdd5b6d5ed6e412e297b8969bf052b0ce6ecda744e016169538bbd5b02acba5da787fa3ab96306a4c6a46fbee5ee274df34a5217ee7cdb860e18085ab3e0d3e33c6a2080be5d92ef470ee6ca70bc3ce32cfc5a40f0bbbb22109022612ab84b0bcf4cf12bbdb65ace3b5bdbf09e98059a8a3e69fa48c997f76976ecac90da38ffa0c3498fb4be83885c73f9868be8a312dec2dc81b586a4db228c67cd06fb79f7e5f4ee62f95526b779386fc084f64f15ad659a0ccd69e17e9d49c223760a1196009bf519ff96767824ea5fea160ad6f70c47b8f379d15b693ddb94b1ced6667f0bc541a2e98bd0e4d8f8368943b590a08d355a0d848dd72d797d16d35b1e99d0af09bcbfd7b87c25876a41d9922a3a361167ed9bed24c5e1898d298bb88c55ce3dea4869f50b82b2c539b8007c61a02878b634d9f77d2e4d08a39ce16f52b8d29798d83e142073997cca33fd0539a7f52d2403ac6e6ef7be727cd1d1e5412b021e9756020220f9b4529c2b70aa713efb29e810a3d9bd450b73c1fd3d0711e4c77c559ce992cfb293ee554ff3c1e7702f5701ca8a7ad42464ffa5f77d7fde6644317cb031dca7b460de04a0798c3879f7831de6251f4535a4351f479a8d23d73cd8b2b20794f15d1a0057d4d3f1e83102182e121fd97513b59d057e1d9796a01c3d6d21ff2d48fa290de83dbfca009663755bf3f9657435cb3de48fa1c3a4f42fb96d4939c7e4282e55cfd5f8a706c28977b04d24c25e347efe3ef01ed3459fb3f32fc72b6f2b9d0974145098270f78a1b2355ded399c6a7b16069d994ddb4421eb99242c4a3ba6956a3afa78e4ec5938c78965b35f447d3c8e834e2661c1713ca3d13594bdaed5a765d17e6867f52579b3f5c6a21f5dd64e49834ac5bb46b7b364afc98e8f0f77252b89ff63b32587fafec130e620b23aefd72bbf9ed36d878f4cac7e4534c0eb53b92d8b239f5ba5df88e57ada4a85a9914d572ce778c641cc39dfdd427f8c775baa76b658a48edb9de74c4c70ffb8e9c86b1de45c20c56082f23982d8ea201f435a20bc3e029a00e784849bb483ae77b628f4ef1f8e436270824c3286e8fa661412dc6924e6db9b815d15be11fcf61ea2c8f86a41e0ab99f76beb1eba79354246e350e9653cb2804ae0bfd7e6d4f6c8a72dd9da90cff3bc27776c93bc434daba7aa6ecdf3021130b044178ad61b6c61c95a659beb2bcc12658b905ea892e8fa57e0e00256ed36894a19463c04064a99e6d15bd453e676d4aaa8d8e6c7c9c44412b97656e54f3d67bd2d6187d9d118f4e0e4f3f5e70682e3239c79ef2d0730f833c72079d5ac8ee34467eb9693a8ccca1eecd074a0e7b28c98ba545945576e41e3782f9d6a5a8d861feff550e0b89c27ed7225a9b01a76b1e5f522f346b28789ec372849b7f8fd3d8b6449638d46abf2197570aae0443333564d3bcf7d8e899cbcd1a3fce140e6dfc463bec44ff47a577ff65265556579bd0a5402afec1752b7986e60bd2d3cee84064baf72f52853b1b2974271ddd6b4ee703c1778cde6ee6a130cfee05c33bc94c094700d6970453d0c26a8af8e062fddb3394a250e5f2c6879672fff92d80627d3a773c54809b030d8e6b7a260a3b70d062ea5ca9f3dff42f0525db708c976a4bea341aab8541c8fae8f8f5f28ac0f9460121ccc9113eedc5ec1e4237f8c0ac93c73f38d4b56830be3a7fb9d8510a626c9f502d99f99211f329f36c23cef3d3102c2e4fd336328973437aacb517d65d0193ac4af29531da983e965f9996d52659aa2025a3775b82204ccb44b88fe27a9571686a43da010fbb40a711b86e4a5a26577d62040229946907474add0e64453e7b4f38ebb9f3a9fddaa89a7c410d2c9a74db969f5ba7ffd6c6bed3e76f6466b4f8fb551db2dc85434d0edd18ec3a8d45ba1247e14417cf84050856035c12c4da7afbd58d659bda5dbaaf38b4c948353fdc3ea5c5fcb492254b21e629123bf651d1dd318b789711826355efaaa9e3f9e9f19d3285c3388d542079ec8c61b02afb6248dd55d44231f339c78b355d380c444dd917c1136aad3f8e00dd5ae142f81d88635f0f1d88f6331a9bada4f641d2424dab5314b7755e81c9e9dcfb1addab9aeeafecd0080f5ceb5a2c4614b4823ef7da1602e0de8e99a56ebe4c86dea2d4f8c6e0cde043cb4526f508a0f6962e63afee2d24489be20999497b108a780213cd747778fc84bdec00e24e95ec2bdfcf273375708ea7b8957633c46a3ab1ea4b2bd59eb4d352ab78dc6db1395f1ab73eea678da2e6e85eb9a4d6bdc7479286b5b6c8f49abe06dfc19a055192b241a7e766c7349456809644a538398ece76bff405e4008f9f5c5e33b02714377a0ae1dd9325e1bd95e8c3946b140b6ff7ec5ae3d7b5f06fee725a27ace09e99f4628bde63d4a14945260ffe23812840b21a999274e3dc426813f34f0ae4a3d585e1d2012d7cb2f022061882912b8ff7a1185f51c582b6cc39bb1c6a0765560b5a89a9e169a673a226f7874ff7238594e1f930808fb5864cfa3a0e81cf4604c4089612f0056f8ba1caf28661d87e307384c13452953242eb122bf1a0d131fad896f5f917eba65371ee0c739eba9d46e51668a9cb0d784261e58e99667004155b4abdcbb3fd93368f6c583e80f7861779a53784f3b3103a0be650a7dd6c476050254080da7841dbd61926845d7c4cf05f1fcc94d4c40bc90c9ed9e1106adf233f371a0dfd138c5e8eecefb26ad7ffd12fbad5752a2d28588ffa2c9f3813675e4b89d37f7450df0fa24c0c9039676134ecb64ed86b214c5f8b873232796910097c3d15b0efa8732539dbbdf8b54a87e11af4d0d3d05bf6c5bbf414219cbecd93e5cc82dffe3676745a36d33678aca520bbfa505486906dc91a9530be0d3db0cf41e0c61a3877b4b208b4438caf58de381d8c528725de9aadcc11667f1d5b3f597ddfd711eb50231bdeaffaa5f568bd967a4d4649a1e3464d9cc6605bfb5ee0e266764264d0b1a448ebae0fbb1089e6bf9b0ed8c0fce194497478c18ca5c9eadf2a1dd2433d737ba1f1074e8adbb341541b50a2603ac2d713855034e99caf35d2928d12c9131011472cf593b1a855123a4e53785033748d07ee474f98d65774c70db079730080d663e77c2535d0bf121f8cde5ae35147453ff0dc14526bbe2f8b2330ea36ff2a10a184552631c366d579e4512fa2ef7b5304a2671ee4a04883a9ad84353ad77a6faec8affd9f3739be54cf4a3ba0852157dda50b2b1cb37d28a6c34ac5dd08621128a9b1f4f8ed8aaa79b29712707f4f03eb780fe29a71c9d33a458fd803d37add043a0cf3cf8cd07de29e7f837b2c378b7852d190214252d909c66951dc3eb641b76259035c09b87e5d15c2706e7b98380861720c18557619e03b01dc7fac5380fc22f78e411f44ad454861aa1daf1cd87d12822712e6023db9e5c4b927e924f1614d8435aecc1efa14d9a7dbf6c8a5b80ab026f1bec1533ce6ebff8adb8b3934463e6a76a6fddf374e941201cab078ea7d57671fe0712d62f974f966e69ed7bfde330c048411a8efe27777f82ed27581c5ce6577d994fe62f10cf0c1df9b4c2dd39095641bf780cf65756fa592c29cc60a28e5f4071ecdee8e77a6d70c7fc0f75536862128910a7de0ce8a334e83b352d19f490c39476f0b985221c081795af9db93747a9482be58349327fdcc2f6ba9c7f8a96c6b39a9e10b5cc6020415f4e0d5aef037f93f1058fdaf96b471bbddab64c5faa9ec8142c737ca9d6a46e6ee6857b6dde4c56064c9759b0a5d2abacdff1031fedbc96f94af9d15ebf1ca923b9713858b1ad1f8c8fe65e5dd8bd608e8f26b4f7c30c9718b0c9d73b8b52259620287f7df90cb9de378fbf4d05ead44d8c115cbe664863892985118dbc85ff27b51d9645ff3076a2321246d0b1eb5a93e27af71f72aa420ade6d275c148406357123b39f4ee4d56934bca1a34f4d3411b9b0f537c08ec56040720c00bce956552dcfed2857775bae46db4041bcd059f45820d4f51b95e30290d36605431b5033879d5e5e6c7bca677f4d8c752590f85ad1fb5cac215d7b35d6bd5cc2ef3e7c66e6992bb4c542e7f64dc4246d70409ba9c39df77cfd8323637c349c0db41a2d41682ef1672e20752364963c90862e151f2f8d4b99797e5e503d55d70baf8ab525b38260757b56bbf5f0ea62f8147a843191be008cbc107244db2e479fbd9c5af2823eb256c5d3bfbcb86a32a16e070b42bb14f2be708be5594ca19842c466811175fa2e60d8aa9a7a399cbe2324f122b1cb4a7c5f19f75b70a08b9e3ef7452506ec2ffd591647973f6ee883051cdbf1724ef595bb24bb0515f2091580d8edca4507317f9d695aac0e35d480de66960581af6285417ef08880462828a0e42de052ed0402655fc79e1ca7b6a515ff15f9ab8fbca9816b0d85a730d2b9204262b76ec20fa3ccec91b366f235f5b35ec9ddad2b8f6761c927e05639960968300734e2d68d26bbf345aaad2a3cf85ed0233bba89a1e06d30ca4a12ccf05c2c7ca8d0d78fec5aa5b599893409de7050535e0845fa91c35f16236253b0892f0a9457424417de3659d287c3d3d849eb342d662a30264bd2ac8d3f9a6838ac7543aabc6a48da58f47f4da6bb6c70c8e9568225d9f57aeedc4eea02e22acd292e8b1480153fe935dbb6a356ad21ae4cfce4a48c76f4fdd8e6a1207596de052e2b4102d9b97d966c7d86aa926e0cf26ee95b4374880509c5090027be50c93475d3b38558fbf7829ae058e44a8846ff1f10f25a3295172624d25556c92508b101f0baf86a34593bf432735d43bfb53bf9311b6a7964ede0efa4b2650cfd661f582cb233ce3f9962a7baf202a88de6e084a0b14c033e25b7abae9defabf769746d993180e71a17f22f5d88bf4b5d24f0f3f7de0ea39836500a4b3dc8a5afa87cb8d7883a797b55c9a4959d33bc56535dafec48e8d81349aa64ba99598c9cf899cee50a213003e99b7621cb37daee8df38f77d9a66202fbf2bcb9fe806471a51fa90aeeb410cfd4d524faecb3ed7070360581ec859a5bcebb78e11f1e8a1366a5f56087b3f682cbf625a663383e6b8d95aec73c547a9ac8e0f50633385660b3b5daf0f10506246b7084b7d6d92446797c95d3d9f42e61c4064a595c6e779094e0ed1b89ace1e4ef000000000000000000000000000000070e1821292c363c", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 58, - "comment": "h_ones below the limit", - "msg": "7f00000000000000000000000000000000000000000000000000000000000000", - "sig": "eb982fa45799835478145c89fd06a90aa57c30fb63f766c19e86b67fc9f5f0d1f567ea029745ceaddb1dce6b82a90b3e0b669d4f13a1d43ba7a16b0e544bd144fb349d93afe2cc8f71d6a5418a60cc3f442ee5150c224b43772c2d491d0861cf4130f15f92acb0091eb0f8518d3c4391b392d14a1bb336ae5cc5f91f2641e4ec0700ba1d48bfdfc70a9c1020195d053ce76301d9a14b5dde8b2ce9e5965eb6ee6d9334a42645d51faa20ecf56eb9731e90fb873c63be7299c4afb6ba4787b5d24267f70804ca5c33ecd20d4fa8f7d29829f59511bb4e34bab987ef031c96c3aa8e6995a0ea978095c0acf0f3ebecb44e3605c8a78328659781758b267071489e4b135ebb52633f2c6badb8f39e236be68a9d3aa6885a58a2172a7f87d69c2cca2e48798af869603ff0007feebe9a8d61c38dd40900f65864366063f0df04435f8ae7ce6166dc8dbe3b710059623b8af211499ef083074607d44dfa3b7244fae28a3154110d533ad32f1c6594858df1be788bca52ba7faf895549a454b6b5cc5b166464b9365492f6ce65bf6d735f386a14aadefce3728785c186a3bcfc5785496b74f6eca808aeb19ee9341532b391ca68c959357f4e8624d766c41843fdf408e7d8be5857cc3d35003630d280b368a3bd55c27286b69b56be0a99774b14d2c97e5daf04d7d52904e771576df47726945ddb20ba97f819eeebab7f0fef25977f7cea68d973c49d353db915b2230b454ca40feb88895f6c317dba532e944fb04244b518f7fbf720146079b30d848d0b1bc36df04336f151ffcbdb4b152c9c11299fef85f4c5c2d8b3278baa2627ed608c0225fea29e3bc432200f8450c0e21800b4945060b3f03cb7c7894340d989752638c1e1f64ebbb1839084c194b751afd389321c19bfc4a0a7189c189e8b880ac1d4ac5fc9719f039def85eac6d1ca7c92584794acaf79182302f97e233a5227e788107780733a027f4e34153eb8d7ee0105f6178d9b68d4ff3abfaf2cf2c3049d5f032d8315e3257e3bed63d370b77218002d6e076a37b327dd15e3a6a132d7aa1d5d88ef778d87166171e5fb01c257075a85f205feb9924f75ca92b6de0857841735f291338e3550da1aa509391872a3d7611af0cdb6ad262b292a62fd0ce6d5e220d7a13387bb6512c74c6aa55ee3d33968f92270686fe157a90dd7bd499b430b411994cfa392443a591848e8ea0365c5da87c3f86314cbcc831f7a0348d2d6ff9591a8370fb54069d3ab0d8b10826fc2ca09cee7f0f422b6bf220a58489805dc1d0fbbd4a2442a047d0d3ba0508afc08210336a73cbd1ae088ac082b9d8620e66518ee3d7130bfd0853c828157ad0ac7d59a73d1a5a88b089c6ee0489897fd4a00d895ccc1282d2fe6b122752472aa76bb3c5a6e5092a25117ecc81e4e92482f996463517e001bdef74669bfad2f412d2670166576d8f012bc5d9a616a737c0d289d1ec165341621482b93b23d68ce3c304247169c2ecbc5da82a7302f9ce8bbd841a74af950efc72e6729a10cf820c39d49fc4cdce1fec3f1c8c57dbfe9116a9a58e9b9437d91bfc8a7c25938b344256e15360868962ed3545b8c804cdb64c1a79394483703060cccd749d326e332f3c61ce53b7e74bb1cc1fa33cd38c75b5abd5b3bd3f34c5067c42944a325846e245eeeac6b00bc05219f8a33e7c19e8181f4b12dffd875ba85ebdac733fb9dc4454e2e02ee47854acf8b9bb5e93fda07e3aac679f145a5f48b608eadee51cdbb9104afd150f9d0705e80a97be22581b988f54373f9bb665342062a273ad2b539effb6b79f78143a66ffaa5dbd0f675faa9ea25f615b30d9e1f3843a3dcd7292f268c905487f6db5be0280512fe3d4392d2d7a3b8aa9ee54315ebd923652112c80951436b83f2474f332e7037a53aca8a31fbe54e403384923ffcc6c85caefe9f3c738d1d8402c0bba3245f98b5e1f76aef5575f07e13e1603aa1829d20885e29d97abf9547b3ef32b95845776bf482f72799db690002b91eba68cb6f4ca77d72e31b9274f92fb097f9ebe7b9ca5cd75eb533749a522d5f69ede037dc5a27419c54524b3fd3454fdd58da5839ed47e670c0f7b3de0094c09e264d87a56e768e76cc4cd46bbbd201922950df15584440eab951e073e6f91a9bfcb5958936489c32d30c635120615df2f2927d6832ba36f488aee9bd9c805e2e6c2173e2dff987efdb208ed9a2c1f20ceffacd781b4e3c47e93dff7dc33db63eb9e6966cbd74515d8280007e7df18b6ea4a02e430797a1807b029ed8c93772b03648a96c50c6641a40b15f8f615c71cdc1e1e248049b22aad79120a59fbf6bb8c66d0ff70e4c6bc474f1292c8ca7b1b760da51c1f708671732caa009179d2b3b5d1e5cd943bc176d50f41f76f71d7202582fbceed21a5e05b091afcff748f566626d8517cb35ea2af32ac62c8a71157f8190badabf76632b78fc2d7039de68277d79a0496f01012c351d01a040b6d92909e9bc65b85c86b72e2cb981778ee99c27172e060b0bae121da6c4194d92ac9148636855b5e630d097edee7390eb1ada32fd0c2f677a2abf62dfa6f3ea6e5587102e21fed8c25f22b08a6aba3519a70972585e81efd4a6fa3f349f61beafbaf2658084037a184014843250edd389fc36cacd01d3c31d931d4aa33ae3cae92a3d5248da118c2184d348ced3016ea32598f5b2051550180605b1607acb526ee84ff182bcc15d435b05e2d2be2035bf9b801608be9f6e494bfbf90215dcc8149d965b373b0a9d154c89989ce3af93dc74d55a1dfb8b963256a6f7c8b985eaeff96cc8fb4e0e1a741dad4908d1429ca705e7e3810eb5ca645a5c04f40876802f6c6c9639294c84f4e47fede4b403d6d76ac71207fbaf80a5b7c55bbbeb77d709f68c3e114b174a219e4cd6e170172618e28d8586dc8288d6e7cabf121ba83077ef30a85f848a2ced20004a3da0c91154b344e467180410539e48ec27fc61100dfab7ac601d108c43cbc5fa3e57269178d8086cd25af44d9085f7496f4fecc37969f9227efd77665b210d369ddde29fcf009e9466c525818c5f34d9a36dc736cd7b21f45551f852b7118fbdbdabad338077c569f521ba40048740c476d629097df980635c8d9eaf0203983314daf9e9a589895ce28c92169f33b9ff16284b1f5581c56d9c73a7a356eab0f4cd121ba1668c9502fe795569db8183bef48d8cccc6d2b41168d5b6d475c2b925a5d176fe3b1d21d54b75662333dfa309d540c4e21d43be23eaf62c553e098cc415e09c935dc171ae12267246863fd4e2ca080c285931a13bc2f688b3f840e53d014ee7bea385583c3f655c753d1fb961b739c4c4efdafba5595b9eed5034349d29e5a7b4232723c7cd00f0bc6adb9b9790e4045376fdb5d1af2a330862036f703bcf2eae0c11a6b47cae3fad2400dfa375a45dd96b4c5b4f152d1340ab2ddecf98285d28e975f1c3afee112b32de97feb17cafd803c2ff3b7fee9fa23172643074fcce7a639d4e3a00c60e5907c32e31eb98ded699de0fa4e34c8e7e59dbe8ef8eb15ff471dbc46b169d0d3c696ba0a355a74c9ea65ddfdbcd5d8cbe92f22ad6ef572d9222081b21bbd3b7fef85a1c8bf216c7b7b1568eceb21844252d046e6f473234824de86fd85cbb8d2c9d1f3b7275bafba86a3757d5f89b21c43fc66144e9fb6341fce3f5283e3d586b3b1e143668fc39e4382df025912af03c7ba58153acf7090ebd5fb37e43aff06dff92c5063ca7649fd757d2afa99521db0a4c6ff2ca1b0d43cd3945a1d7b0eea778da23084dcb50f525e94ad7bdc6564339f37ff7b091cb9905b328b0eff09138ed5b826a51a05b020f247f9d40fb0340de7ad7456e95dd1a624bcaa5e96eb66c775857dac583937d1b5e091038e1a269f56bbbf17fcfed8d146e688edfeb167074ba3623ebf768d46c88beaf74697029f797d58a3169e516b48ad1be87d6db7237fc3feecafd2917db7651089965209bb6d931bfb868be56d6fdfee3158f752a7d503f41068c74ba89bda10da55a6d330ed0b1f233d19855ccbce4a051f2748c849d6ae3597305108d53b03c73c9daddcf47853a4d974011a1064418bc810a8316fd165fa3844e584da227b7fb4dc82d3f15209ec9591bc517391b0b197d29bad50ec19d7854b40087dabbedbae2c6de3580239bff0e8a7f79836b441c048d86306d4df902cf8604c45c8985c0a12f27123f1c9571cb31e7d937a331eb6b34c40a5f9e83f5fc2309763065b21963b0ad5ae2056dc8a5f3306860c0c01bd30db187e32c3acde47e219e44f09294d63bec2c01a08d55cd5b6b2d29a7ae2ec39c5967bbb39fcabb73ba809463b6598b68dd0e5f1e0e1e82c5c66a6b5c6248747f4cd9479899749aee922c22fcd8b434899684c333899b57904d4d817d59c3815ea7435a084251f96d3d5de95f8be82ad7695696c8138f7857e9ba3dc03ef87a1bda5d7e38572730633fb9ef33b10bed3de386be89e560b69955c888c2bdaee9fd97f5b22a25ee7ae15aee3f0625700ba592adc7f12e70cb5703c7af031245d4279e8eacc72b52c5230e9998666d00efa2301a9248c2997c104d093c26d3a9b4f9ebc532872948913126a2ac6f9deb9ee15f16a298c4474efe0810ed6d2980667182475d5abaf0d26e87b54566cfed1aca7a716ff6d284ec27ba3f7b76d17a317b284f7846afbb67707d627869d00534500bc2bdf317e6683b0b195255c39f8b4798b1261d16c9b8ab4530556bd6c7248dea6cb98538b8f4401826d7e5b2a0635a910c662134eb603cebe3b3f699bf0bb751fc103fbdc3a8efcdbe480510e0de968a21f50b3f0eedca3d2d0f661efb86108f5712c7bea553ecfe1b43b21336d361b7502ca721618e122cd64731f4059821a354e57836c54f450d2c5f8928fdcd9d931cf547a22175a9b398ff80e98d5f643762a7e4a7dbb72162545e663ac90f3bd663d6ddc5c1427227cc28c111fd522528f002874a48cfd54c313db9d6b68a8f03a2116b458b9561db3b37da96649f96bea6b88b5474603e75462ecf2d05ec6b76310f3d48da77adda399526e1349b57961791d9e361d875aa110858a6f8cb494d67fcac207ad81d19c9d29f0c62cfa4948e1e12710d6a8829bc21e52c6d3bb13ae9fa5f340647d515696510bfffbe2b845492b47236c74de594d623f858c5c567f95a9d369d90de7ad23bda5513352d8cf5ff4bf109eb793f630fbe4917fdc900068b379dc4fca4623aa53cf55ef9a695d8f4ba637a264025347507638a7ea25a51639d695d9d962f6524d9e7d8aacc37cd7820b6d386f7f41811771a98a8f451a9b37676389135e5a8887e1d53a601baaaee46641402e5752288712166a00603c55ef616642e3eb2bef8ce429882fec988b348300441f9fec3c0b5963c54ab8a66657825081465b2616fe3f8c5c5d3051be3a374ded89fa14483cf4d8e2ee6700fe0d172b0b5f7d37794c4a3cc324c95e92237386dba5fb29efd1d39176af04c34f782f7ba361f7b210fdddf0b7b93cffaa861767ab174b31aaf6d72c158276fd1321307b274a30dd67ec513d090f6c0b9d85739d7e1f14f64117a13cd4a6978633c4502021bdac582af67922584119c59d820c41864787e5d6bf0f499343db1411dcb8b7ebb006deb2e7634e6515e37cc177fc6b8c9217e3c132d341fb2e4d256bab6b9025a85f5ceede5e203b2da0880d002aeb5cbede9b81808f734d1faeab095360d7c7530addcf0a290d15f40a108acc4b477af177f89329f3cdecca22c6b439806973c79d24880b584e740c73ebab3c8f69b0097b73f6861911068c1018829be395c56a33a7fdbd66e010c3ea5b943763c7fac10a15aa52e51b7ecb73ace6c06a484e134cf58b91a3623b59b36edfb6ea701874270fd6cb10297a12634e862559f87f307d3a830621733c24b0fde0fa68a91416318a17a508e21332c932b37a4cde4c2270935a346b12a05708f559145f888319fb660de9c02e81fa7cc0ecea3385e3734e83243b1b65488dda72e23fd315c018775f539b99ce34dc8c4a84e785559bb76d8c09601ef39989fca23339c0793a67f463a72bfbc74fcd0afdf30600488f749ed2e8428c259715eeb9663856ab909042974e97e9309dff7d58344c5fc42ec229eadecc5e495fe28aeb8b12b8e11a04d309422e27579239cc9f044cb84075cb989b64f14c371a228d5f4226c219e3f4db4ad76ecdbc7093af52b11cbff3af4fb99fce9b6106d724e46d53a47ea98c0f392832d198bbd68846f94f1fb71762fbb3d5f846fdc4959a90aa13cf01028163979370f9bf027b6e1def577e50ea8c1897ce394ae89c0be16e37dae748622f36a335b4afe2c9a1c8f224e0a7fcc09aad66a2883bb01c962f7a0921139baed00c15de4d1e4e28c43ffc2478ef50414162e505482bbd20f1454616fbbd3d8ddfd545a61a3b2e1ef0f174f5e79848890969ba8b9eff209294c546d757d8283bac707385a67718c90a3b3b5b6ed273c3edf15182d444d7e8bbc09131a28333f434b", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 59, - "comment": "h_ones above the limit", - "msg": "c301000000000000000000000000000000000000000000000000000000000000", - "sig": "031504378c478bf373f111f4632a96b9416f4170d326763c5b0c08e32e8efb77f7a8cebc706954cf6b9cd6dd1e46983c51800aa8e56e4784ba02979a4a3d277ee9d69aa87ec346a30c74c69ecb9f1dd69238f113bfbbf1f5549821f3fb3fe15090436cf610eed1cd67f70a352945c44b70a24d8939f27a09ee996581f1e5830c5d8a2884773f9c3726a0220c5e5a465b33a8b4993f6483c8dc237960b9f53687f6fd166c8f9e930793fe6945b11dc31e77d1ef1d43666e3947a5bfa7639bbb4054594271f5619336766f8f8aee2e6584217eaea754e8b697dd3776dc46ffc80ef63de4ae8f292206ae5a0f0dbeeba6487b5096c6afc2f9ca7cadf8363772c577de9ea334f1b2d407a86e3bf06956b004cb9484b06d80478367dcb0bc91ec1c82cd6490f46db07bb0b182a7209ede4f641cce12432f5b329afb4a18a1984a389aa3150a284e3a3d61f5ee0c820ca31254d05de720c2906c87ebaf233cf0245c991f6f4861e4396f8f64d90730550fda3c23723408748cce995eabf0d630f33bfa53286b9693a4b2bdf33d579d36bcd419fd98c7d13a8ee631482b7f94ae15b186f75e7f2d50bd6f6b8a1996d33ccc8082728ed019a02bffd640784b58dd1414347a3778e9de94941065493107b57ac6290a8904847763c4db9924a379b024ba5e563a49a5b4c9605a7be5723e476bd0cc1432fb8f695858fb37764f5cc08bfb49f6f6a2eef7812b99ae7471d702fb035d91ce0b6b7099e5133b2196de75f87ec7c8797ebe0a862c8296f040eadda2483f6985e14931bb16b7b6b602077090dca0aebe87d08f3c232cefe4df5767180c0b264328ae5fa2771e77794bb49d56622b952d4ff8ff0c301f3ba15ea42a972c4cb1929cfbeb095c2c5cc8c3a6fdccfc41aba04626afb100c011bad23fad9d54e0a7b45fdb25400df825299a9342c1e4286729ef93894a851f29d42a60c676f571a8572e140923564863a6814cbba7ae21880cc014e08dbbfc32cf0822eeff39683eaca17c3ddaf7cfaaed9936743587af369c2b28346bf892e97d1c9b2862f3fb212d578f27f7cf699c95df94c110ae7e53eabca8f8e3a13ad6606b98a4de8b810974c846b5e508be1a0b68a862f5226a8580518ea41ad82c1f38c6c3c10775e3d68d74bd733b3d03bf15d4cee186f3538afb1d7e1104c2ec2a76faabc2a3dab4031d275d1632d03f49f3bc8a04d8a3f8348632f0a8d011260cf1bc8b2953349d51fe41dba11a7deb389e8a02f47b3f4396acbec304b733f559807fb072dcc593b205f8e4f290982c099e103babd686eba2313f315d5883afad8186169e5eb71335092c6361e7efbca48e08cd9e5d8000a481375d4c2372321bf76b997ece8e288be500e0f7f8d8073c25e0868c9bff7bed106a975aeb4704104990878407c45cd7aadda950eda8e9b8e40486e9776fee78d92f40698e8de429bc906eac89e452efb23c61ea46974a8ea6e8450b83dbb166e972ba28a2dd3c6dc40ad741aba943aa4d5fee3ec59dc0b4e08464952b27332237f1d8a653c5b68edce6bf0c9630e7748e7f2915df23a621001f01b6d2298d381a8827e0d5804921661d52df0184669ecc59e9bdfd461410f087cc4170e0837c8c7a60973362b33f6b6ca22b1b3e80fe0482f29b19edd74b9017a605198ce9971b22f0a6203f2433c556e858fd0ddfd19e62ce2531854c57cc19b57865fbd0e099324da4ab29a1fe310595cc3171b9bbfd094f8107513f5386889dca1207553483365992c0406028ab21a67f48a60ec6dde387e483a5759e3bf06677c5c8f38341c15cdbc8e8a65226e7d9417e230b845bcc3c1aff072cf04169b26dca100095a463172c4ebd4a80a34cacbcf4774687886cf85a87a523087e28ace60b0ce66f27721f6dcc7e06aa007f8f12d99151729721442630a9a9cbdcc44545b6ea1cc522b989355d5153fc2bf7f78c805fde449063f5de40504e58afa41b84edea85538f3ea4d640708207fa3777e11de127c370ec25f406db74686d46368674971adf4079647d71b9ce69a4a8f1f25e3a4445f227261b5bdd70657c6b915150a5b05bd587a36944ca9968ee7acf02f346f9f763138ad978f85e57e8411b8343ef102139e32e146a167b064520cf9bc93a71b9e1c39555c1dda9dbd5589a5f08dfd1397a4f1b7b8804ea3fc5c510744526d20f0332c6934faa2e6b1c53f3c4560f8281a6ecf87e5d77dd685f84d7e7613aa4116cbb26b43e0a5cf04cd8a16944966a9d2983f73bbe75d622d759334f511be614eb5ba9b89c78770ac47e739ac76ad0e09e14f111613d265ea8f9e153dab08f39514c108353883dbbc30abfd76f1c4f67540cc9d80478ec9b73d6f6a29bb361d50cc19295ca601463751780c8c3443160275d5502eb4c823fb09a756ed5ae52cd1ac80b7fd327c4184f1807890dda962c4b8c4448ba380a87cf1c9e462a09abbd5a894baa8e060224e52d6b2981661ce9cff0e5877d59bb64dc5d9d4218f4365084f484a75e035017030a405bdc0982ab703621b15ed20001852e0d15b72ae3d4279180a95aec512cf75ba8d172cd32c827dc8d3af4cf6fa83d0f88d994dd4720ad93a274165711847750c472f0364175a0e3a3760c46d1003ac1258ea71b4b4d9b5c03014cbadceaf78978408cce9fdf0e51d176ef18ad7fba2fc83c28941dac1f21d1a20f4d68cf3fb3a700278a08a6e8a7d528da0e0ea2af4e6c1f935fd3fa1f1ed1a4d4fb71f4016c41c9acfe9b3a09d463ef95300a5c0616e52392de4440b52f06f9e2d283cb1b757dbcdbf456cd29a9460a59b076d130aa2253465ecb37e5a6acc952447aba5c60f77ca54827f7bbee49cc3b4c29a19379d91e4594d27917f85bc8444823a5986c2d7ddbaf457fe4979f5211c490489bbd33cc4c6a586c861f4eb19b3103d0c2341d2bed6390129619cbfebc343249ca39342f79a90af8b51daedbeac91eb326bbc8d016cf797868eb8ab731769dabb507bb4e25862d2931bc7a6832cd13788c9ecda8f5289bc47e80b9dc1b9de6020c24b9cb212100a9dcb2fc7c50b868b9bbb0343e8d1190b9ea6d99137bb55bded17756c972ac19a95cc333e18ccd4b11c8df3b0489eef1ed7162da05c8a407e596902f969712b61b91a6239a67ade31ebfeac592c155754e2688464f80204fff6faef3b4c320b8971741791f7e28142cc8dae4e28751339784251254897733938094fe985fb8db9f942e924ce1090c2c7270e09b0355e9c37229cfc9dce93d84e39aa424229832cc2a2e19738844434732bc95bd487ba5b0a10b7677aa95e2ae236edcc9c49357cd1b711bec8bc2925154b07f7f2b5d9e1d1312396a53fed2297d29b00daf20ae768b9b786946ea0130f06be78697ae2d00c1d2778bfdde3b0d6b04c5f78a55e381195afd1e5ccd9d4b5f4fb48a884eb1397e68548bdd3d19e63dd744b1f652fda11337cbed96cffb8dc5b25edb8ae5ee18ec172317d5b9db4a3a384c387b9fbd785947cef367da8e971ad6367f11a41d61d7188b04c8de251b98ab8a6da367969d1e6bacf893483577a68998b773078058d5dfe0b105be19f66f46bbf4d69bbc075a252e0af5156c479f1ddd79bb69c6ff31abd70247b6801ea9b701ade7aa383c59dcd805194a2528f0a37f412a5dd461a6129c348ed9be82a2b117ada560132cd49140c6a9022fdc8baf7638a62a24edf6a5bceecd9125a8335724aebd95c1e1ba9f363c303fd90bc45cbd299df92d8c7440013fa92f881a864642cfbf98be52f2fc8924fb8c96e8933e1ab11231eeb7026781f59f7af58d670b478ad2e39a5ef52ea24dfa9f058da520c0ef29485fbe639ae0ae500d05b267a9cb26ead8bfceeb14cad0e9df90772c4da45b776aaa326a4f99d287a18d2aa575c423a78e95d31c56b3dedcb16fd54f10b7497fbbdc233f9bc6394ae96bae368ae7dd301bf030e7fdfbbf69d500daee31f649fd323d721f4737716bfbb79d2bbd82bf088a690880a59caa43f1bb8178ef6220224aaa0e44339274403fbd53eae59b6820d7d3e1435a5f32bbfd894f4093c78c0c2e27157518b75bcad4ca05799176c79b18c08864473c69909598d42561955cac2b518563f254a6b028a5f4d97626fa1bfbf4502a10dc1b4b00eb8be69459aecb742393dbb40af9cb296a7ae5da16bb7205a4d23197e40db15807567a2d4dcff942b1f45e672a547cc6fcb9b200fd762394c95440ce2c81a48ae1f4fc4f22754348703eaa3c9c9022753b9e64baef53f129446bd69af52664ced65dd43c7c77f72f3c25b196864bff00aa081006bd308570a1135289d84586a3654fd35679f568a669cb8a981113c04b6d243d752b577847c42bcfc3b642987e717bef51c9803bf27f90a24263d717c031da55716245627e2f00f9bbddcdbdfaabe30b9f2dd4b139e1bd53c34fbe7aa6c1ed37c5f6924491a6bf9ebd092a386d076d6085d2bfe453c33a86ee68553ff67ea6a11808866b043dbc62a313fb3f6a2ceaaec7ec61e3053e60ec3948f0e0a0a4ebc3827da6b04c56d3e4fc883b80c4a9a4c6144a0bdc901bdc536f740ace251310f6300dabf0c692e3c0b2eecd7a40771350d6e2334e0d802922de8e5432410d52c7c1f3e0b515e536c1a3840c38edb62de0d67d5d704e6a59039222f3ee8af00aa9f17f96ff6edbd29e1b1fedf5aaeabd6bda357633f665573a8c80d05a011be451c79df9388f9ce625f5e44397126d8a6a9daab95b6757dc97df590bada0089597cc40c5e74d7ec9f0a2619196c842b6d3835590e04745d7b1de698ad208ad42ae1ddd5ce7df5be575bb22f71edcf5c85096ca81d44340c8df4b04415f5aed73421ddb1249a2401da0f985783f2a63aa63c0550e5f76fb2c8d37563e45fa6dd5af3113bba5ecd7b03c06b72bdb4291fafb4309c5da0d4ccdfafb3266d571a3bfc221db4171cf1b81b5d9ff448567d738b2e5b554bfde2d4ea58af58226b2ee426e8cb274a6df84f5e6af83a7a9f7153f6dde35ff01c03c0aedb76624de190e710ed1535ffa94b8023f68213c933c689a835e216ad18390f21ad0aff77f9fa0609febd51f6a8c728cc5c813327d3e8db08628fd439a1a56f9be3ebc4d8edc03831f71853f26e28a741841882169e74d559baf0ace2acea81c7e2e07129baed9a9f524523d9780b855f2d93894f37096d8a5659ec7cf5b9449dec412be6d4c07b4f47c313cfac73ea18ef3227a3927766c716db7a390540b57902148f6533e208580a680c14c45cd354eb6dd711323eb83c10abb40576c1ce001646c9409c12c6aed0fbccf69b6cdbd56941c82e1cc73cdbd8d762ac92b399f9b0f0ed39f080fb042d174002814493aa676950c8eae14e2c33e6c1edcd9f7cef43b881f0472f5d58d11aba293278435d4bb1a60f0ba5210964db1b841c023245cfb1b1c41472c203f13680c776469d3c641bdf8d3baaed8ea34e7def08a62f6b0d57d5ecf549831b4ebabf6fb7a554a0f4d33dbb2db4d9f76ba767f2a9d5581701bef99a1892cc310713187a94d1e63edfd49556bfd81af0fc42a381446258462f69188becfdb65ea30f3a8dab352924629e8b679774f772b02abf87f74f7ada5860959101edb50aeed8c7a9e1cb076d30e67c06b43b6c93d5f6b205dd5ba922304616388a3a02835b3e43fbd251ad70ccd7f18aa06b8cf871e116bce93b20b6e9b18b1f9ca6547ffe2391b5ef5ad68ecd0e998d78136ba968be097d285aafdf4182d642dc8f8e590fcba0f5b7567e976d4a6dc1570463f82396fe38f2ce151bd46ea191c81678cc168efc0bb5acd825e0bbaa806d188b6c6586a170a6dec7ccd4501a12cc9d3b8dd9d26a172b02642ff90e27347db8af86132b2d511af270546528231ee3b5a335aa238577f8c6c71aa95a874cff204f6058aa8c38919c422a7810e0249be38b6728b320db372d769bef7c495f3d0cd5da2b8fed90374a2c4cd469c980efc1071723bb18fa50fbdeb5bd9049eae7549855ad2b5454efae573d82bfbd7b23bbea93a2e7b7509b09762cc70f2741a640a7ca7b938d6c919669796602fdcaa7d0c0be406d977fa66889f72d307fd341cbe37c5ed0baafa5e6988dacf2eb0302e0f32e3619372f549efdeaaf33b155d9174c960d5cd189c158fb388c071ec5ddea4436041cc38b3fec2205b79700ff15426ef1aad2402a0403560b8c9317ac1873306b73db8453f574c72c58b25d713e03ba774684d14ed0c2cdf290c34e91fb155fbc85f8261c5a65d63e5fd7689298595ab52c8ad9c4347ff0adfc27311103e009386eb546392e3c120e1c160703d77271c3834f33fc10cbadbe99c875336d8c5b064126b772dfd376f217e7cd1e74828b07c9a23262a05eadf3211290f76ba6629e761f8749e9f34f344a26aab65a874b7cfbea0368b7a653c6176b3c11955957497a9e90b1c4281838b8d9ed9e74a6062761092d9f22b2f35772c3948506f77b1c2d6fb0000000000000000000000000000000000000000000000000000000000000005080c161a1e222c", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 60, - "comment": "high_bits called on the edge case", - "msg": "f100000000000000000000000000000000000000000000000000000000000000", - "sig": "f847c3a8e237500f6bad80e7ecb13cbb431d5b2c062473e3ed9972888005cfdbb0a72a2c47391cd9c4fcc64ee38dd225f79b97e42dc86614fc966dc2d27b28530738c2962dcb06cd7b40a492cb276c05a7405380f3a1ae7acd25e6ad0c54080a6e1fc4be2f93551c000d5580da3f8d0022e2c3ae55537000b3972b7a6e4f2d74dfe0da6f8a9a60c064336c500ba441fd70683b3957db6f0642f9805f70a3b0365a325165ff80cf40177e709e728ab9104374add7d17c074cb50a5177fc247de4a3b6fab0c911da385c1d51d3fdc76b40297c46441af18698ec4b0d415afb10b50bf675d41aa67d96084d81568a1a6853a4680db4f12d6fecff5c2b5089b4409442b4623c1c0039d7b292c5e44c264e30131faddbe500dc46311bd671415b628ef025aef46ad4e7ba2b690218e3dc0f48154ff89725946c90c42633e723b71241555851982a08fc230d46dbb23e4d3f650564ce82528e9d973e9d391e6fe1f33cb4b6562f67e1610bf0ec7034a728e4ac561d9dc8dd30d98346514a552f9030a3a583254bb5fddc4949ac556ba5905acc145097c6f2d77bda7b8d317c46e974e837bbfc16812d3003fb709952304c7b4b9e41a2ce048fa5f9bf31559b88687f943b3d5282d3ffe6454a264e886f3894476a2e7fb60745d370e984e753408af81db06e96eee904c71c318f454de6a9a2f43b71d315c55db4118d3a8a69132b7929a091601ca271e89126d3eb5f1cf5fe41e28df2e79621c9fb9d37c2c47cfa89d43571476cff39bb2fc2210f71286d67f3fc1b4ad138901073aafe8c5124eca777856d633f635e853d1cf3292c1356298a0706a8a16b47ac68f32bc4c4fb507f487c4c8a4aa082e2183d908729cddf13904ae698d66ee34d981c6c6e4f76137c2392dd19e23ec65ca91b4a6de3473710b1516fe566c32f512a5b0ea1e4cbc50cb9effbcfeb0d9e776fc14aef6d49b1072177b875d7dd5ade5d42943d2e9c15a87812bf0da47fd326b1c18493dbda22296bd8d248fe62a14ede1f815fd142816fb357445944bd8f8c20d48f22114ca89c8a524aab9c5b824b3116770811c8a7860b733ad378afcbec4678d7cfb6a996c69fd27c7d8c508dd3269782cd8339a1087a3e1ea8de83fed21158cd7a46808b6e9860972e1f9887f8ba868fc3364b925cf698f51af4f274fa96ce46fc87f1c37591881002d7cb9a3b0079b9967a1bed9e11491b6dacf8737439be9749f71dbca697df03fc3d8b3a712b9f820ffeb73c51ef9266f6a403566035d9c6a26cc16c69805fdc1918c5f17f4a7a4c79bfc01cc17fcb42f9f471ed50c0dae924f1562b419b01a04c0d2bd7e5a6a14b8f6130798ec3c458bc0bddc3acf3718d97df11250b8a98297b617b00b5da9b657eb795c916bbcdade65f66c5cf96863f349337c0f998d279fd96226d2494d4563449c86148d471a037fcabfa2cee4a20e5453390568697b5eeae6ffda976a4372437645c797b6d3b65833eee15ff68f8a7e85865d5d7a48127fc186c312273d2dfae12f19b4fee2320320571fb2c666f459419d698223e1696f44aa031477c3f24a35ce9be8ad18ac52814095aa4dfae4a39a588849a8c7a6d066f75b1d3790c5f5063b91667e7ce478f86547bfebfcbf02534c5e1e600c4d02911435c610ac4b456c8ff0606ae60f4b763de0aeeacd90c2632ce9443120b580a1dbc1d68376ee82faaf4368d3a912bedfbf58c86c4fd739ad5c8f63831a7a4fffcbf50b768ec732cf03577be2bd34491aabd80b2239f5a39e4bed9c35e0aa5c75d1184475b1015ef6c8522426ede46981a774bae5e554f3aba9ac1404f653946758a13c2ea898859462fb0b39fb287af8ebbfa815b36c919a084eee951717e13106744ba81b130321d63b6ded14a5be65426cfcc38b3f09d4a847fe7c49b344a927cee264d7147b40286d8d85b7739c089e8f94f088334603a00b7818f3f12833156242de120884264cc4f0625051a71a325f33b46a99f5cac5ca52686a540bacc49a3c5f5f48b2b7c97bfb71f1e83ece986db2059d379f5a97f28cf83bb8d98bada5e8d076b8e1cb55b9a38276a07a472db05645f90d364f5572089802fd8ce1cb40b79d8987d5adf6ab921ea42f3905c3b15080653d6878fbbaa1acba2fa0dc648e7f30e4941f6b4f66b2dcc0654d349b2c820d317f9a9a27948f241d39d7e88e6fc063c93c1274977ed33ceb4887d7bddf8002c9305def0dae1293b1aa4b7da9b8ac918b2f1e72da09b0889135c8d423143aaff2a9361452ffc5efdff40389b05c2597124c95fbae36083d35382c20449677f8a6cdd18ce38ff0ca540b2c4436fcbdc3cfca7a4ff7e0424b8218542de48e7903bac1e4b311e0c83b602d802f5c5e4a826df2ba2489bc484131b385c81fcba6fcc1cddef71218c6692f96dcd89c65f5cc453cca66d69951ced0712cb67dd703176676b29e7e992b1accefe721005105209ec303683d4bd756921a8d0e8a365048aadaa648bb2a672e067bc99006fd605c61cb50513ac5c6c68f1184c08421a900180a73bc48913bb86d25bf4946753f7fed56cb7e2c0adc86aa5e89e0d362298d08694c49cf93f7bf9a2309d9a79c7996447668d95a4d642cfe0764269c76a99967f14e2f275d87ae69dd76c83ddf6a67d8f1dfab8aa9b3164c54515fb030f276954317322d050da9ab6fcf44367a5732f7bdfde9a95d8279885a2d08b945c3334f13fba09610c871b826738f62501a286c95cf781c2dcd66985bc28e16b09c06e5087fd971d19ce54296463bf6289aa628b6843177f5e2260551dde806040de2e2357fa32d71f3edea81e75420d735c17f5573d2e395711488cfeef06fe3ffa969c0c0b9ea794830d5106c5c546f17d7461d379a3e8396d5937703dc48f6c0dbf09c81ef6e6b93abfaa5dde0c85d2139400e1cd983acd3aa72b3060180997db8a18d092578007519ae8cae7291b54b37c22aac75fe0a3b39efbf07e2076b4f66dafac72c1605ce1737d9152458c537c40c40406b907800ca372b5603b605edf38b5b5657ee6fd5e136b6446aed92e4d6cb746ca338f7a3e760df656beea8946e2814fe64bd1082b53f692db4cb6a7e206cd603f37a53cb790cbdf1efc607a361c0adb589e7c22fdb52ca923187fb99b0261dc6c2cfa4087ce8f13653c1564f06f39ff8bc76672d2c9afd596c3b5b06c216068e5b784596e976e9384c409cc89be9691b75b094f8a7fc30577224df8bc95f1dd04a7a0b20ac55a25e6fae2acab3d9ebf02e3f77b883ab70af95f73c0794d1992126e7a6f1a458f404f9ab1250ccfbdfd320f42f0682be2a852d45ff099834fb16fac7f64b59a01f319f136f0f3b85f3680d48f8f90b5364f6a8897d84e61d6ea7c03bfdcf009de09cfcea5e7e71c15f95b7879a118b2ded1cf1dc5fbe8207dd8f67c9034da5d1115563c758c7811fb9f3adc8246b03d66b3fab2a0401ea9e053ff597d1f07eac50870fc605ec79865317ce0379c6aec095eb311d2ada1b034ba66ac2019d5d9f27bf9126ab59f828a76e006026f71993d6d792a770e6cff5d0241a32f1d02219bbb3d22c22d31fd17309cbc255fd70d18f0c0e58b8985f13a39f5f68630527dac601d882f3ab4a99cc61a493503e1a4b255dac8612b777dd401e0e2bd2aa61b058fd9a35157314e3974791cf746d40e1563978a6c0011be0ad0d05b47822d10412ed08ea28a6734b598389f51cdde0504de214aa49b578e2321886fd2cb8c294cb9288d5c76a126bf50234db64a0d35b3ef7e5b5d0f3483e2f2e3cc35d773af4ccec628c4d7b9f88d223ed153e68b01606d9361cb8ef74377998a07090c5a376105ac8446b2120367983aaa123f02bc77c793d64a5d14777f515253ddc0e0246f31191b3998e8841be39cc601e88630f76a8f319ddde3868c2abb46d48de2b63aa734baa865eccb3627dd21f05430ff83cd580ab28e6e4bbdb06db8098bc41d3d278e475ea7ee8cb192a6b18879fd5af9bce37af38f5015a9d0ed7197c99e2e494100f84a65f9ce79f0176c9fd511fb83d046d38cdb5233ebd57962a0878d024a270afefd0ca40304fbb5dd2961603e12ac6fe8af532c8f00052b4747aaffada313ab90e7ddae921ab4f62102da5120b5809eaf7a8958451aafa590f71d33ad2f69a32b8d6c5c04f2298fb03714df522963f7f37a1c0c73603481199bec5320e8fb5a2a5d1f80bf4c46852ae8ebffbe14d0b3177629129b81f8406a55c75ee1497236b69248cd304b697de6f45db5338e66ba31b7c95964895d981dfd3864ca53c130131a336d28ad33e6a9c2509d8e79ed1b5077b16bd0bd362266e8b550b7886d4945b77fa76099a7e414d6acff8dda84e6af739d72feeb4bb04cc45966fc81912bad42ba285b7b1ae09e9e956e35cfda60a97f36eb2055f8f77171fece867e12829f6aa38f26670cfc7fe1372b96528d8e7e77299ff7cdd758570dbf3ca93c466525b319e97270228410593ce0d0cf53518bcbb6cdb09706a34f56d1c01e445f820b27cd331a65e466703f560eb2de159bb6f5e1accc17e79f8a380e96430452ede3d4cef87456dbbddf8c6bf5f5b44c05b76d751e781df3530b7c4f289959e13a9e90a807f79ec5f8c060be63d14eb69d7c6e65690a1033d5f683ddd7da391b5af577ced449592fa7e43f7ccef4789fcc738070c4d0941ee7c7e4e9c9ae6de7142849b8ccfafff88cb72eb9039598c63362e0dbacb0b5ae9aa44cafd91560a3776176f1ebaeb3b4dd91ac3c682b7df64b6d45497bc77ead6ac74f39df461fa40e629d5e2c891f6348ae6a849cc535769e8f7acafd54c98438b393711f67f1e946475fe4e4ed988f441265df533962a9d83b84dfe6194a17f06d96d047f1d854bad60a73b0d830bc6766dbfdd91f9fbcac897c79725079722ab6ea929d0505c03c3cab031ff5dedf4669c2c7ee20bcea2104e52b6047e4032dfdd606db11b0d8937aa61a001d330f9c4bd8604532b1bd20d281c3950bf1c9e07d101bad3b550f567f713bf307a27b58f8eae0a9fcede055672636b760f1aa46e9f46bfd8812d9c7c127164465bfd004d1561ab258e6f070bf77aaad31d19f7d6671d3bdcc97194ff2c2cb3a918eddbfc18331bdc344e968997895820b601bdf3cc2fcf072567f5d68daa3dba2cfdf7474be80ca885531f0cff0159ee19235583d54093500581894f8d3742f4c946f1d3d6081a0d5662b071a3a3f3ca715384ce06abf05ec8c88a402fd2271d1fc8a33604e410979987216f0cd43f769a67483940d7b5cff9b7b76f2932fde82992658ee8eb85cbfdae49f0909fe1fdb28c06b2edb864ddf659ba479873094ba89acb50d8d926533b701ce14fb33d1fea194c64ae74c48b1c856828a5c7f115f298068b7ef09e15f4cad62724a5d4aee61afca8b8c415e5ed3b0c64818cf9158d3bcc25f4b65b70c57d07b31dabc0ea6fdd0e841b84a0f21951d1a06502ffc2d6ed80a80960b1eb365a8c6f09d3fbd9c96d2061ffeb7c663f11ae7232e6145d0068ec57a3ee3f61e041d62409f7e07946b8d8a8442b2cb3c95c841ccb74a5d81f8816a4022f0ce9ce8b36330dfda56b84c680b98a3a146edf288d1d8339e6014744871ffc7a00ae01e7cf994494d5fd3b46c45aefbd08ec0187d73af64e5eb8c6be3e431e6cbe17abb0258bfb9eb429387f4cf27c256f8de3b49fbc9a97805bda7104a2ec9c86c3cb41883eb166c51925898c0cbfb4fd19d68af5112ae8f9b447a2bad3b9c6930344b8f871396cd31d9f1968f6c66cac32e1882d07fc84bb76bff380739f7e9a80969a6eae73cf4ecbf16744a44026392c214ca4bcd795ce1d047e2fbf329798372a1f449341c8319c61d61fd903511b5b8aabfdd9999065e77ebeb23d923319c2f519bbc1c8232cfdc3d1a84aad9c0799947047b108d7b0eaff3d4fb1c53300195c12b68f32316d833e3d3a81ce63d1d8f94e205c224f5ec56dbafad34b532fcee9fdddf3ff53a6a5af548209ef66cdf3e31924e257de44b27cc4ffa89f2d170cb0d7d0a4ae4aed17c2531f483cfb0bf417495dfd2ddcd5aeef9f1a35a94075c4789940076ea9b76f3342ec0c9bfce205856bdd84ff92ed1848426978f60ddd541553c6979e6827dc48626af4ffaf7ee52218941a648db0f3e7ec19ed0c4e7f11c5db841d1015b20984943c854c2adec57ce872694418d5846e5c4d18e438fd442f92c543a8d0e2c454693fde738829a3d6aacaf82097a26a5c8228ca272399bdd7a88b954e4d6d87bc763acbfffe78f131d7f36eb2759502156574699a1cc443bbb7ae99738f54efa8f63fec72dd8fcc08d6e18dbe0739dabd14e96c283681ace2d3d4a42d7d5ae7ca76012c7e92ef090affcc4e1ef655e9e52031c6a25982ab4ca5be8f6336f984b3ffb9cc12ba3423b5a7a7c9798c6d50a0e7d7ea9b63382d3d825727c96f9fc226a8d8febf2363c5392d1def719577d8eafc1e5f3090c5a64de00000000000000000000000000000000000000000000000000080e12181e252d32", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - }, - { - "tcId": 61, - "comment": "low_bits called on the edge case", - "msg": "b306000000000000000000000000000000000000000000000000000000000000", - "sig": "2f1d3d2dbe0b990f3b215c756104e0fd40aa1b0e106462e339ba21e2bccf1e9e27df4b6c39daa9192d26f26be59d0f43869fc77e68c9e138fdb3f2a8ccdc9de00580f892e1751087f0ee9a71bda9d7e5358c8259e0611ecf09faccfd5bd62e6c350646dd70b96857abd58c3b92e1aac526d2941243ea3b8ae607a2d0bfdab40a2cdea32023b52bac32f07864d73537840b0419915fc8a2dcedb1c699822511178bb4172dce5454bbbabdbde0cf6bba707ca3fffd820f3dea742c218350ad92121edab8e6659bb00b0c8037456b75830783ac819a74b498fba05fce63a5a8c38f32e5e9946daf6e42cf1af404554fc9b5556de1952f37db2e3a4f8a1193d9cc3811037cb784284da4c24b125937c2cc534e76c8cd5f50f89e708cb29724afe7f49145ee771ff06a947c3981f62dd3050a23bbdf186c47c3259f9433ad2186dc3e2ba0af022313bff69da868986a607347ee2957e27144294e532b7b870e46bb1160950159c41dd97c689338da52b05ceb08958a703869bd6d965f3bde5d1e27dbd0cfd45a00a7d912cae7eb1c67c4a5b939f9a84bbdf3b7572b89235bdefad510440b62f4225fe3219ed0e2d62f466b6882ac37c0e8a8f1e6688da9b4a227b4f9a5143659a3b680a51e22477c8f2cb2ac2492d4ead99465be655db27193ac4168c6917edcbc79ce692721703738c2232388e52526ca46fc6f94fe6430eb5e2e59fdd2de20fea2ef509e5d5ec552ad567e10e1e15fcdafac6edc3efcf43bc1102d5ca7ef8fd01826ae5e6971c1231ad6b3058885dbbd2db95c712a54f9935a5c541fe40c04124522d04b04a56cfadce84a4d4a8acbfcebd8b37c1ca06b2da1d8cca770d9d1fb6ec69a5f90fdc038e2917803a5eba3fe3f78ce0c0f3c2660d0128c3d4e4c1a8b46cd36beaf0076dbffd6b536bbf784a43d89af9bca5314f64b0ed7d164d22095188499ceec04d46eb95b0b1b5403a2b843190959430c1d48c9b9b78ef8c075c53f59795792f65d8a86859e7d5b00d23fe69428f0be2f0fb49fa68d94be695e91fea5ce67917eebe238b4fc9337ede8873fd70b07a339d4bb33285ed39fa128a73f389070e80d8cf042ea5551d99dfcac8d87034b6ce0a854ddcad67bc2b01505b763dd563ac271474cac6fa8d8fe4b9138bca906f28d9f579cbea03dada28f9586cd11c414587bafa3cb7120f2be29f3376ab4db2764a440751f4a17154bd12ad1098bdab261170f6a062ae31e141c86ce8188b1927bbdce9438af2fcaf8f597194b287735c0b8468bbacaea3ee344e4945c625d7dae5be73968cf4039a77ee5e2471da741c722ef05fa1827b8bcfbc7c3dfa4deebc987b28f3fc6a23be00ee281a6e7a164d3e7f637ae011e85da8d7e4e99c7e600d6e7bb63083a1a8065b2b88fa32d73c4ed6ba8e35445384a4dd6fdaddcc2785191afed71052b021f9c23e57b67118446817427ea35c7aebbae6f1db51ea7b6c97c1dc2a6cab470d760ae51ea8c468063f85e4edc74b8f8f0960b4bfaf65bbce764ce71a4d1a48ce2ac21de3cf21c43470ad504ac4813351fb8596fcb71dc5cd2af28d3ad1cc954695913b9b3166c91b7fc6744648a1b2693a19caf85b61030ada6b72a6d0fe513158cc4ff5ae368bcc1473086f5a7ec3bea7325ae1ce1d5fe60a38455100a02fc3d0ebe278a3750406bd4ed301d4c44d338aa56c0e999c3d400498ea664a2172a77c56a0a49c6edf9ba4787f5785396f6140dd2c8e33f36221c30f03db58d3ede279e928e5e3089eba9e63319ff16df0838fa20ed3c60cdaf98dd22c961422aeb9ea7257703b5c5247812bac051ca129df4b8a92197c4aae4d3702e3898478b3aef33bf68c5a436314b66eab32dba273d62ea979e687cc0d58746302b2642e7d3cb44286d98176b1dd05ea64418a432b0b3a9196297e304c5ba24029aed58cf6df52c8f1a971c99f6964e165c6f26a91469c64b68dad6c84929267463b805381de5b60486bfe3178881a3a43c1709cc3d269568275e7d2a83dfa603e7be228cf5657def9837697cdeb45916f0fcaeab063ce84db115455cdd3626b2f2a1d80cb10ec5f6fdbb88ded8170f75f3d553630ae590dbf5f312ed3fc3ce7492205645e20e59252d9fa586878d1a2481ccf14ef96b9e51d8542d1fde81e2281d911331bece1882abaea74d1770a3faee7a9d176e8c4e3d1218c42d2e8f175b4542d7d24599bd41ad38a5a5799c54d80002e70102db493126f7a682ade4fc1fb5be7dbd43cba3769882a37d8d6ce9c53f2fec3cc82f579a680c4ad2224a55f70ea9a3dab459e1dfefb128e3b96f5f85bab7982f9662a7bcb9ea76cd4447677d3ff65347e98323eb9a89385d068d33402dd21d17e60767209cf15366316fbad977c9af3e1d392101ef0d3950a18fbcb913026bc98ee91d4407bd7f529925d59649ce092c12b4ef11a3c683d9cd8c37836ebc175d851180dfc88edbfec06dfcbbc208eaaf4cd2b9d9acd4cb03356473b2a29dc20562f91cb4d6f10b4617d9dc309f3dfbd6c49415a13b077facf9da4d0e657289c9407a3076426613050a765b1434d15ed0e599e882e8812739554d3da385d35dd210ebc7da19031b9cb3abebf8e1b6b47069f03721eaeb917a9d624039ea8329c16f9694f856840419d9b7be0e80e2fd5f79a5b82c9d4a7adecd12ebc6f5f0cfd82b4f6b41bc59526fba764a6a9b8b37715bb9ac02b6dd69819029e4a93a1155271c8843d2c7deab3ce2445a82a73daf4f02bcf78bee4adf374be197fd653fedf8da2b6069889af8f9712e23f9edddb80d3cb9e6c6fa3634f989c94cbfad26279ec6b336fee8d54f494abb15383cc76f0b57e6738b4ec01ad6a888facd52ba5708483d42310215661d16bc66db81f88f31c8bdb9689d7838ae551feb003653ab67b1a7942669442d1612d4f2c8eb1f6a05bbe82cc683b5571ba87a70345ec41695074535ad8f53be072b1dad19113bceb11284b13fac81ac14b9a2ecb9cd204a43008dbbb1fb94aa6ee548583065f818a495ee46bd409fcda1fb5bd6fd6004dbd302059535725644bb57dfa29bf3b059261cea909198d211ecc37a3aab9badbe9ced2603be9a65c78175473699a17f12fb107b8e757f1b44a3f3bcf8d2736788896481fb0104805ab051204fedee6faa910b84f792567999155ca0e014f26cb572847241e5116b280e533fb2b7e6d14f6756e56774f817dd7eab747421c012f41076a5c4f7086b2ca0e27fc30eadf4e7865c5beb83c7fd56b4d658c4b24c77ae26f2a7d4fff899fd6e1565950a603e956a37f61cb2e363e0dea23fea270e567da018d4a634286cca282945240fd37f2db80d2c4c94422c89a70751b162665d796482a3c33e86b86c7b5f93900bd8d3014cae590a1f2edec79eb5be1222f7eba7cb1b3f00ec710d0a2047332933c632e011a63c86542a398a4d7f7d362d5fa8087c080fa170777da50dc9db0cf4742a6db0c212fda18cbb2f24846344f5b92c955940800cef2216acdf1b4ea78c36dfb34b3cea831749f9743dc69e7f7055c626792df12a6a66f8012084a3b2667beff05aadb5a4a21ff4c86a3d1d117c697f27492d45682f0121c3154d282fa989dd42bf83aec7ebc5b639bf4c85b76460eb66ec9bdb05cfe5d84cf3c7e244433d7b445880febb564e034172da9e858e260640eff545c1d75117cdbc60dc1252fc0427533fcdbbaba1466fcf4eae5504dff0d0c2d6ecf7b3f3c149530749b7eea6bf90145e2242498abf35c2971fc6454d1d20bb2429f0c8f4f5df351adb31c7ad5c667edae81091ae77f0dbe2ad0fae84d72578d831f88dedb1e73dd96dfdddd432f5a74e477ffbe52a1d8fed3c188606ad6f445ffea0ad9c6cd5d57eb8bcb749a3e9afacf139b42e3829f4ca0211a2f95e054b623d6545821943a8ba879768aad73a1626129734283b49ea368d45cc8167da81beed4ae98267d498cd50398ec31dad03706ec6835993301c47366c089948d51de4d2e83741ce8d89cb8855f6a4fef7bb908fcdabb1790154cb2a835b6ab058c9eca2c3e71b7aad6f03aaf6a6a33254a4f6969b30a5f2122655a73f6751ae58288f48aaae2075d55d47438401d7a38ebaa327309f31fd140763c685e49a3a5277ab041942bfda955dc69ef9d8067dccf33ab54158e9ce0601d9c311d8ca0eb326aa69034005f68ede600039fbf1e4c531aba2efada21c87d270494d692f0f3a064ce8eb626e24559981ae4be7ad0b0dd927ebf540bd586920a513c9ceff1b9b7ada3eb002843390b7bcfddf852f2e04c2d668a98941cf5bd15297b93fee4823e9fdc0f6682e4f8dc846f3b0021df998fe813fc942e69a649f285865d6a7e05c5d4f8b622a53637dc27bf41583d4f15adf7eee4c4eee91a40fee20f9e5a3baa4e46be7320032d1dcc8b556976ce8353309eb382f3a909e8a12cd1d933c25b96e1774a4235635052ecd148ac12d089644bb216f8be26d5c9bd77a78b27d0172d20d5a7f7ef5a39259fe6143f1a78ad10ab4a77e4d7c0e6cb985e7d5c7d127bdfd2a25d621037025269232d35cfda7e05ebf3d3b6a702b2ce37ea95c45a27378b9911d257ec7c640fffdc1bf2bb2d8279c4d77f1839ca1c0002e7bd9b58b420d3ad49d74992e80de628279595b0cc985ee889f29f7be0e2f0c20badb8766bc8bab64e585d917b6b1087124dee4b260158869aec468eb91355d107311650c03b99ddae8b5331a95dd7a57b5c73cfe469d58f387d911bee1939b66fb1eda0421705a101f008aaa57f2fb56beee39d2ae1d7e1e4bcb1fa474a1c3ec69feb299db77591f93424b37282e4b554a723fbfc10cfcb5d87118e6adacfc463623c40be5ef3de0d85b38a214dc3d433dcf15f9c23fd7412f938672585e75ce687740e48767c5bb0b4564cf89100d48dbdfc6bd18eb1e3c7a129b17706a714f9d243b41d26d6c40bb79c1207b7882c586c63660d9889a8d7d7054a1dda0c68bf34b9d8c018ece6ddca120f05671d9a892030939196f77f3b9a0e8d5dbf9b0e15d2a3b2298c2d7d4b73041f5f678de48032e315a2c201a4e13570203e708cb69f57e87f3450e108e2beaf750af4757f7bea824fe991cf2cc7516bbf07baddc4619e7fe470a0901972df384c58104e67e7ef352f8d0459a069b0c14da565a011c929c193241c8a81372b9eaf7b5c83913b77149b633b9344ad24b0672421b4585cb5e2bbcbb19cc669f481d32f3a9a363b7a4dc123b5b967b2a664132ea543080704de9b12f8edc0c40443faa2ade98f79c01ad262c68ceb8ae661199736857f14aa756fa12915b382abb0076485c6ff9ae6c2aeb3c60806a9ce19a21bcb7a0f28ffa7b46735a4504cadc2d9e18cca11a697428c11b982cf64e75294e4367b1bb1381a20e25ea49f94e9b33201d9330a57a8f5ad7618cbd3fa029bf1a46689950f85a51f65ad2fae84d017aaf813ed816195fb8422322d49ad25e34a0ba68e3426807217abad97f17261421b3ad5e4119eb0379673ba28ef773f0b1ff25e818a38694d1e8af9224e6031c50079ddc70c1ea8d32f95306aec3ab28f2151179840ef2b37681a4f882f692df5a3e5b63af7f5eaa1fe6af6b2a92dcbb77d9731329a8bb68b857b5d139eab1fb5cf9e24bb12436570c0997fe84d79cebe6e17f4d90b206d54d9bb74084448cb18838768338eaedd5e25159bccfb03f0da7d9b40969b5206375dd2d1f4a38d9fbf5aa943f8bb67ab330355f64ce70df8e6b67a7ea20d24b50102a38f4c7f65dfbc4712e387046151e4653fa72316a98256109746397b53d59bad9807834923e4ce6977443297b9d038a031dc3f0164673cb657bcb49732fe1a4bee79c05c4ee85d3707fefb64dd2a98f51cecdef0abf8b1b15de4a2dcab24cb418ee21b79a8a8faddf02b26cbbfbeaa3bef5a8df710ef927e6d4bc44caf454fec972e2cf87a26ec33802f9db81e68d718c45eae869b5092ead15993aeb43f2db22272adeb592e77fd8d38ff847b1db5fa1421507e4615ede77a2b54d14accebd8ed10a93e68b9a610bbd422c0d4ea3e442c9f43aafe0c205b77ac17e44fd614ce06f87a4a7b2e64a85c22f530b30d1545c69dad264d27b7b7f4042f3ad638c3ba145504b9b3190f03e65981e6240bac7f2e9ae7d91f6f8cffd7f889da1ab575150bcc4763d69bb517295202343e4b7abfa0b66f7556f424ba43293e5a524bc9df761a42cf9852e3af2ed563cc5f3dbeb9ae5aefb66ea57cb9e73be1d1b2835ee3c7c3d205aff79d3e3f1a53b0b1bd17141b649bf9e2c601c191c6ba65566615eae28858b125247d0391e5b634263ccc6998238edd3489e6131f5ef842955b2ca6c2ede94d88635d784eb88a4b9d7897319ecc36e87de69b9c24df7fe597463181550436f41671edd32ec8506090f7bbe3fcf4c7e1c2642445e6263b3e4011e4043c505314c667dadb3c4eff51129919cb6c6dbe1f2131a40415154b9eaeb47668586bb33445b658ab3cbe8f10b4462b7c3d5e800000000000000000000000000080d1720292e373e", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "17a508179b35057099111733da28fd1a2265de7d8ab22d5279f13bca84cc42a5b8c9644c121e7e1b81723c5295be288fb6c36bfa188b6e08d913a152350947fa2c8ccc3fd01b319f65a2058a1dff54133946cfeb408d0b6dfde6bbebd7e0591cfe83b8b5452ceef6c855f7d33e06a0d269345089ed0d3ad67d84d8a4a34d16836004cff125469e8c3387abd788b620e30c1fc23909117a0e34c42a6631d9791347b1b2a3c9ab3082416211afb7bc3f6ce630a7019af19f736cdfacb1e7db66b65ef56844d2a2b0753d09283a7a0b66f77596384e95f7ceddd1c4ba20edc11f1eaab695bb963f6eda1c383754aa372a0d7729bfa6e0f142131c2367ba3f89ce3de6c357f9a7225b7cb85f6b3e8a3a122e8501fd1446b8152a415c19dda1d2e4590cd994f6664b4d1abd7381468c3a085abe2741a0cfbb81880664b271677245c4a471bf8bb8e0192eb32e4fb5e8560f3c50d6b19a353e486d0fcc2a35ac046286e707e095f61786d92212686a65d39b6863e0f8cec1e1997f2f845e4878ca9df650c746765296790863e51d012d32dffcbd746aa2276d04c0a57cd1b3d6ed06c0d66a0897aae5c49c97b6f19ae829baaafbfed28a52c05963c6eea9eff69528294207f8cda75280f7c486e6848791c8e37015479f2e13c28a9fe654dbde11689875203aaec51be3da7cab1cf31e4ec476c0c830cbdd04ac02167c0a6fbfdd6548b1fa525d235c7e3fca8d63e6427503b0a45c0bfddb428b837c32e8755441077bfe1c0142bac357b012a46545bf4148d465472dcf89c9d73b62357087e229f53a450d3cce41c8ee21a9d54b61e34a794f5b1406a70724ab0c3712c49df231ef30a956075e907c51b63dd1f9453dbe60e25b0f3cc0354dfd7c9119313919e77cb2c92f544d3e5302b8827603e936b567e99bfe9904932585a9f01a5a1b5bce07565f1d84c6b1c5c86259e1fefcff18cd06861122be6836be21e40be4eaf6bcabee8f634f95520aa914bb51c54dbd67d1b9dc5e38831e786c283979a963a3206b98e339edec4128b0502d4d47813869713e431a529a03c7f54b50123680f2b7f256f5d2b40642203259b9e85c62253d5670ce372193f28b5aa48ddd643c54756a2cff808c109f74772961d8db6bb8a17547c8f29c7f5ff3ea06740b867d84917e07f3978ad0281a20689eef58467e768b6178a9b36a567289fd39762bb3e4254031b2798a4550857f6af369d484392cddd7b48eaa2942e2cbfe754d5ee2da2b7fa71222e4a525ff5224d551a778ebd828e4e0499adc74ff0d59a5abc78ad6a8abafeedb3c99045a14423507f85597b1a7f540982f7d72ea13449110b442d54b78029b4c7fe3b49396dc6c3b7d58792538fa907963de10a4b724548142541cdf1512e0f7ff1b10a93de63541b8cc3268b4de20ed26739ee8973b6507ebe48965602c35fa3f7d4278146b598d7d7044e16e97e9351f7c51ac25573b7232ae2432638e9166190e7f7a7dcb5096ecb5d10017cdea2a82b4f56c7385041c6919a7e36e11beac77ec3f25df44e7b596c1542c1e376de3667c0e903fe25b57c338e9d93c5570c484f0ddab4f57d38f292b23599d9efc7a9fd9e078aaddca0acb1a196d6c45d3c8be6f39e8cdbe3299e370b262e0bf6fb5f005cae2b12879289d00bd8039de6a571c310d87557f5c9a4f64a0bde7177a8464722a04bf87fa2cb0e312d4fa6e536c61d65dc2c1baf144b0d1d1d75f4c860626ff773933efa9941d105c53a1d92c4f7c7bba4aa969590acef1e50901870f59715ac14d9846d83871a77367be57c63f88bc2c02eabafe678f44925a3e605979282fcd3f284736a1d346c033cb782dd615e886683fc37cd87a91422857774c63c6659096eba393c56225ed8c3485b4f89ecb07d53526281a6426ae7d67cda52fec5ac32320caae9b96000bcbe9e8782be88cb1ca6dcaffb74ef04c77e03a994bea2c89e4fcfa44cd0c9f4e30705a8b7b20df8c76b05a4479400e07db03d243e9fe4c90d34e9245f1e574be9a388f5355482077e4e98b919de024e666fdd7d51ed2a0d58a823e7497eb07303cf1d6d5f10a536be980220de5856727e5c13981839cfa19740988e7771a2b984f53ae3a5916ed881a4a90fe524f0bb3778355882864f8961fade32e656fcf9f524e748c8196a1f1bbc57bf8da7b36de9b0080f0c7bb8487a2b7bb7a81a8ff43a2539b367c9a48c70041520f05ca3dae316dbbe3118218216f52b7bcdba7557c4c9d861803a5e2ee01d3682e1261d7cae0a99fb8de909eb2bc1e112aa43cc2fa9c76a222bd85faaaba5d9ec2198ac45a295181a324a0592632b89e2752582cd5e01e1a610e7563faee10b76d853109e257e7c0c248a9fb7933f514b07b4f4e3a4a3d2cd22e8cc45ebda3bef5948aa050f01eff85ae98d19f69c51e67ff89f2df0c5268acfdd325e84591317e05cab4f9e6358f249c4ddf4019fbc8f511549a733898a50efa9e0793083de0b15b5bf78d9f63d8df830d42df2fefa27b89e0ede2a702eb9467118fc0ed44edc63ad1b1935877c34843fea06fdf388bbf83e501723a13cc6cc2efbb9691fe28fc1d45270591e5bdf7aa1c82673544ee29d9e6c9da3328f21e9729bffd7f4e56de585909679a74037105fdac3f51ae35f69d9763d2e4cfeb1d4a8fdce99bf1aa21f866a9f523b2a9549e12258a4d19900cf5db37b67da19b23563bd1d701c6106fccb28e4689c62e1a6cf1abd763d7239c2258b765610d4478be9f1650cb8d18923592ad0024076e52f9bd0a3894fe97bc0a1646b4c37f62c27f32d0df270260f47c49a5caf110e4cf80168a7d54b1c70bed9bd5d9a143ce869a05cd44ee266aecd6bfedb39be79e7c7d5c11a99575ebc0f389cc55a4fe1469a2d61b70bfe4b74e3e27521a037d2b9f4fdb377231e2ceb214ba90f6953865c683215203ce963875c6524c01b789e0389a9f0c386eb236f0dfba6c95df4f28ccc7ae7cd473f9dcd20817cccdd211bcbc78b064e936e4ba2813df531128428ddf410e6ca07044aeb4cfcc0a16c995ec51c8af16a541ce18dbeb69a26635632dcc24ee52a5eedce38c502cd0e356ec31341c893f92e6063c3a160a53d34b85e92357a8ebaaad8f206771be43ee48cc409825a7094bda529ee18776d9e67f1fa1c1419514309d70ba2443be2f63b6943478d6c0f56dd058731e53de4c30bfc7d915e9284a56248e81944392881666680d4991f04269ec9a83b24b458ed59a6c274de452ab3013c103a4920543e6a7d22dadfd764f6ea39d49b910ee0dc216e547aa5fb4382a72a568ebe83ec00416fb5830dc21c24ae72416602870cb52c3a8a1c4c12a4b287b9b800d31c287ca161f404a9e598a5358d28b3aae43e534846bcd0d7a9c7652ae01e6698c79e315aca8198f36de45af7084b1cb21ca2ba0ee3a547a7343a10ef9e3fd17b0a4060badd1409a0562cba25b84fd578268fac53cfbca08e6cf6e5419f57262eb5813c1d1324e0df1d483ade08d8f6c62498e262485ac7c2872b11b42e5c1b797fc12e838b38a711d364d45cd1ed35f7faffdf4b0fb0eaa312fc3d5af77909b0649cbbacea10c9831273922b5b05172face9ce6cf324edf6e2f5f5fa0a9f0463eee938b30adf3e55664f94d274cd87dea901a7e08e8", - "tests": [ - { - "tcId": 62, - "comment": "short public key", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "IncorrectPublicKeyLength" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "17a508179b35057099111733da28fd1a2265de7d8ab22d5279f13bca84cc42a5b8c9644c121e7e1b81723c5295be288fb6c36bfa188b6e08d913a152350947fa2c8ccc3fd01b319f65a2058a1dff54133946cfeb408d0b6dfde6bbebd7e0591cfe83b8b5452ceef6c855f7d33e06a0d269345089ed0d3ad67d84d8a4a34d16836004cff125469e8c3387abd788b620e30c1fc23909117a0e34c42a6631d9791347b1b2a3c9ab3082416211afb7bc3f6ce630a7019af19f736cdfacb1e7db66b65ef56844d2a2b0753d09283a7a0b66f77596384e95f7ceddd1c4ba20edc11f1eaab695bb963f6eda1c383754aa372a0d7729bfa6e0f142131c2367ba3f89ce3de6c357f9a7225b7cb85f6b3e8a3a122e8501fd1446b8152a415c19dda1d2e4590cd994f6664b4d1abd7381468c3a085abe2741a0cfbb81880664b271677245c4a471bf8bb8e0192eb32e4fb5e8560f3c50d6b19a353e486d0fcc2a35ac046286e707e095f61786d92212686a65d39b6863e0f8cec1e1997f2f845e4878ca9df650c746765296790863e51d012d32dffcbd746aa2276d04c0a57cd1b3d6ed06c0d66a0897aae5c49c97b6f19ae829baaafbfed28a52c05963c6eea9eff69528294207f8cda75280f7c486e6848791c8e37015479f2e13c28a9fe654dbde11689875203aaec51be3da7cab1cf31e4ec476c0c830cbdd04ac02167c0a6fbfdd6548b1fa525d235c7e3fca8d63e6427503b0a45c0bfddb428b837c32e8755441077bfe1c0142bac357b012a46545bf4148d465472dcf89c9d73b62357087e229f53a450d3cce41c8ee21a9d54b61e34a794f5b1406a70724ab0c3712c49df231ef30a956075e907c51b63dd1f9453dbe60e25b0f3cc0354dfd7c9119313919e77cb2c92f544d3e5302b8827603e936b567e99bfe9904932585a9f01a5a1b5bce07565f1d84c6b1c5c86259e1fefcff18cd06861122be6836be21e40be4eaf6bcabee8f634f95520aa914bb51c54dbd67d1b9dc5e38831e786c283979a963a3206b98e339edec4128b0502d4d47813869713e431a529a03c7f54b50123680f2b7f256f5d2b40642203259b9e85c62253d5670ce372193f28b5aa48ddd643c54756a2cff808c109f74772961d8db6bb8a17547c8f29c7f5ff3ea06740b867d84917e07f3978ad0281a20689eef58467e768b6178a9b36a567289fd39762bb3e4254031b2798a4550857f6af369d484392cddd7b48eaa2942e2cbfe754d5ee2da2b7fa71222e4a525ff5224d551a778ebd828e4e0499adc74ff0d59a5abc78ad6a8abafeedb3c99045a14423507f85597b1a7f540982f7d72ea13449110b442d54b78029b4c7fe3b49396dc6c3b7d58792538fa907963de10a4b724548142541cdf1512e0f7ff1b10a93de63541b8cc3268b4de20ed26739ee8973b6507ebe48965602c35fa3f7d4278146b598d7d7044e16e97e9351f7c51ac25573b7232ae2432638e9166190e7f7a7dcb5096ecb5d10017cdea2a82b4f56c7385041c6919a7e36e11beac77ec3f25df44e7b596c1542c1e376de3667c0e903fe25b57c338e9d93c5570c484f0ddab4f57d38f292b23599d9efc7a9fd9e078aaddca0acb1a196d6c45d3c8be6f39e8cdbe3299e370b262e0bf6fb5f005cae2b12879289d00bd8039de6a571c310d87557f5c9a4f64a0bde7177a8464722a04bf87fa2cb0e312d4fa6e536c61d65dc2c1baf144b0d1d1d75f4c860626ff773933efa9941d105c53a1d92c4f7c7bba4aa969590acef1e50901870f59715ac14d9846d83871a77367be57c63f88bc2c02eabafe678f44925a3e605979282fcd3f284736a1d346c033cb782dd615e886683fc37cd87a91422857774c63c6659096eba393c56225ed8c3485b4f89ecb07d53526281a6426ae7d67cda52fec5ac32320caae9b96000bcbe9e8782be88cb1ca6dcaffb74ef04c77e03a994bea2c89e4fcfa44cd0c9f4e30705a8b7b20df8c76b05a4479400e07db03d243e9fe4c90d34e9245f1e574be9a388f5355482077e4e98b919de024e666fdd7d51ed2a0d58a823e7497eb07303cf1d6d5f10a536be980220de5856727e5c13981839cfa19740988e7771a2b984f53ae3a5916ed881a4a90fe524f0bb3778355882864f8961fade32e656fcf9f524e748c8196a1f1bbc57bf8da7b36de9b0080f0c7bb8487a2b7bb7a81a8ff43a2539b367c9a48c70041520f05ca3dae316dbbe3118218216f52b7bcdba7557c4c9d861803a5e2ee01d3682e1261d7cae0a99fb8de909eb2bc1e112aa43cc2fa9c76a222bd85faaaba5d9ec2198ac45a295181a324a0592632b89e2752582cd5e01e1a610e7563faee10b76d853109e257e7c0c248a9fb7933f514b07b4f4e3a4a3d2cd22e8cc45ebda3bef5948aa050f01eff85ae98d19f69c51e67ff89f2df0c5268acfdd325e84591317e05cab4f9e6358f249c4ddf4019fbc8f511549a733898a50efa9e0793083de0b15b5bf78d9f63d8df830d42df2fefa27b89e0ede2a702eb9467118fc0ed44edc63ad1b1935877c34843fea06fdf388bbf83e501723a13cc6cc2efbb9691fe28fc1d45270591e5bdf7aa1c82673544ee29d9e6c9da3328f21e9729bffd7f4e56de585909679a74037105fdac3f51ae35f69d9763d2e4cfeb1d4a8fdce99bf1aa21f866a9f523b2a9549e12258a4d19900cf5db37b67da19b23563bd1d701c6106fccb28e4689c62e1a6cf1abd763d7239c2258b765610d4478be9f1650cb8d18923592ad0024076e52f9bd0a3894fe97bc0a1646b4c37f62c27f32d0df270260f47c49a5caf110e4cf80168a7d54b1c70bed9bd5d9a143ce869a05cd44ee266aecd6bfedb39be79e7c7d5c11a99575ebc0f389cc55a4fe1469a2d61b70bfe4b74e3e27521a037d2b9f4fdb377231e2ceb214ba90f6953865c683215203ce963875c6524c01b789e0389a9f0c386eb236f0dfba6c95df4f28ccc7ae7cd473f9dcd20817cccdd211bcbc78b064e936e4ba2813df531128428ddf410e6ca07044aeb4cfcc0a16c995ec51c8af16a541ce18dbeb69a26635632dcc24ee52a5eedce38c502cd0e356ec31341c893f92e6063c3a160a53d34b85e92357a8ebaaad8f206771be43ee48cc409825a7094bda529ee18776d9e67f1fa1c1419514309d70ba2443be2f63b6943478d6c0f56dd058731e53de4c30bfc7d915e9284a56248e81944392881666680d4991f04269ec9a83b24b458ed59a6c274de452ab3013c103a4920543e6a7d22dadfd764f6ea39d49b910ee0dc216e547aa5fb4382a72a568ebe83ec00416fb5830dc21c24ae72416602870cb52c3a8a1c4c12a4b287b9b800d31c287ca161f404a9e598a5358d28b3aae43e534846bcd0d7a9c7652ae01e6698c79e315aca8198f36de45af7084b1cb21ca2ba0ee3a547a7343a10ef9e3fd17b0a4060badd1409a0562cba25b84fd578268fac53cfbca08e6cf6e5419f57262eb5813c1d1324e0df1d483ade08d8f6c62498e262485ac7c2872b11b42e5c1b797fc12e838b38a711d364d45cd1ed35f7faffdf4b0fb0eaa312fc3d5af77909b0649cbbacea10c9831273922b5b05172face9ce6cf324edf6e2f5f5fa0a9f0463eee938b30adf3e55664f94d274cd87dea901a7e08e80500", - "tests": [ - { - "tcId": 63, - "comment": "long public key", - "msg": "48656c6c6f20776f726c64", - "sig": "ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731", - "result": "invalid", - "flags": [ - "IncorrectPublicKeyLength" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "5a04d37a8c83d373ba07da5cf96806002e3635ad8add42ce6ee9902dfc9a1f27fe591181ea20556e358180d2c1699f1a30db0ebbd3b0f7cf63680fbfc5030b438f7f510f28ea9d273744f87aff655e3012eda9eb8dd66bd4c1dfe9a02abe9155c5d489159605c1003d078ab3646e57a988a2f045aad29a209f2d473699c714e3236a17493b8325ba4d2110e6dcfce75b584a1d9496903389a94c21c87013c4a2f5df49a11713801bc46c2c889bc8dbe042c96e83c141b1dc5bd81991f665c6e55871b60224ae4c22449f6835785e8a228486b5591f9c8eca8e4285bd3c6a38f5ef56569963875d5d1fb787b60a099d4bbe8c6fb31ec79210cf4fdf6fddd72352b8a2cdb36b93d0fd4901c7850967a6e80f1be18ac4f2b2bc0124c8d7051444d92271946bfc2773917b982c8f14f68224a3244e288929de500c8ce1697e99857fd79fa244e859248ea3238e9d40405eb7db688599eb1a97e4a7d6bf319c693ae2653f34a5f60e38d59f4dbc224492ce1deba29b9a3e9e6066bbbeadbc9ca4e63d8894d2df24ea6ec8e04097c2d625a54ce2cf4ca137b2578767e1990a655a7aeca4b2949be7ba8f7a479cc7abbfd36216e1d51632400ee839916033d94ed092c0677b46757864bc7c2e620534778b67c0b0345c4cae026aaf5973fa33e202489261296528920493249c3dea4e7bfa282c55bac9649279bcbd4bb542fafb2dd9300233599b7703c762a5426bf4f995122d054cf6d8251cc3bbb17b05eafd6e174a32ad1bdf5447c0e16071a7ab76923a6dd9909b844134ab12e200b9349cc44cedbb788a83f3c7bc5ae1aed25479b1e24f90e775b1dcf76706d6e95cc379f98003c42203b23c521d18bf1564d4f6b0a7e6710a141c51b22255c3ca6495735883b8f5835791617a76c70175b24543904f9464dcba51e004cfd7a08de162e7f63ffab6557ace427e45025a18dff9e9fac6608e25b882bf2ac22a932c6d2290774d63f48c3c4716442deee577fcdd5c941cdbfc27c7785a85aa822f436543ac9a16813be837562d2033bade3eec6a04b2744a4ae9239a35b0481e7875c1cb415a964dbf584673acfc39d8d0fc1901b03ea576c494789fb18f75b205becb215521ce53c753fe44e09d538a918565758b651da38114527ea9e238929636632263f4caf0599ad18937520b41647b841f1ce36e029d42e714ce0bc2389db71ad2ff42c85d0cf3358227cc5cb3aef164ce90590f5f03c9645f75eb16c33c21c31e04c8424d8560989d8299ae4f6b2fe94a599b6b950c1dd837bbb4e8241af25d881565167ccf0345a19b377e0c5eb0e8064bd55a3ba5839230e428b686c7fae39081a53e561507d781de10056b93c4ae6824041f7e8148b72bd3cdd08c432d1fb72fcdbf47690df5c3fd8e5897d564cc95d24d1c2c11c6aff710dfc605afcf1a72fcbb7086f3a36709c3c7092214e08a1d9b3b261349c84fd19b4bdee3fad824c42d5454af62f281cc73334152f730d844bcb1466582120659ae4646cbecd6f0ea8f638ad992a065612be339d67a9f8f47fa2aca9054940dcdd1bcb1716c5cac0231f3e8e8f64847bbc92ee05893c46e58207024197b81e6be21ad1a4b69cb9eee28dae6ad09465106cd847fa28837020db75584c300ad85cd0a5e3adbb00ada0e35bad05abe93c67890535d6cfa1cbc86ceda9d240861584db4cd756efec12fbe698bc2df20cbe4163946853e33e2b33f15d9f84102586be2053d3265278c04beffcc77d07e797b73b57bcc25d4f72cb2d14f7fb0c9542f7f39464e2a8d83ebb269ebc921d346935a8f84a4d27847f53d7ad3933e6d7c9344ed947f4094cf81a8e9cfbef7e8c47571c57f648250ad98148b31b1687e7a9c612d1fdba5883314e95eb3971131fc2a7906dab88b7caabdc68eb0e2c98b82de336c5b65e7fe036600ecf3bc194fd7eb6886aca88b69edcf8046d90aba18fb9e208e1c7a9e0c2eb755656cd9acd0945a134c65ae71c658773a0c21c19abec88ec384c45b709194fe63fcbd736268a0891b91d0425e0c9ab3a42a081bc9542fcfe5d51dfd6ef5b4937a1a3b3a6354aa5d3a4c5d3a97eb37ac60e31b87a0e0c1d265365a2a07800f71d95c70ed02ba6136766120cca80420cc20c0623a67217823ab38f71c1615d08b6c70d22aeb1f3319458410a688e1874603e95331eb97430c4a64f6521e64fffd6b3ac1c3e54ea50d2b0782eb128fb37a488d62d12b8cdb6fe3762260081dde1e82ce8b389fddcd07b68354fb3047f0e8805da072aadeadda36cacf0d98a13058ac21a5188f25cdc8c05cbf4b8b60252044a2b518afc3f88556e6c138b82adf56df378a09437671593a602d12e8b954a03094f3d47db8da875c37f05c84fd42990434fe52d7d1d89f586760a0bf9e775ed5c78bda1a1604fe98dde216f0f2aad7f91872a620beaed7e93c858878631f1f84ed83e278618e491b1b4648c6d272d22b1fc0398ad3a80c33ccc37c9b811d756fe9a12ff857005bb23a0ebc9a333465b4da51723fb29252efba7b3405426286681334f5d7747b363cd15262938a4b129735ea9c5591165ca7308bce1dec7a3c418dfe64304c68dfa5266bee3c103e0b28e61906cab1e2b162bc6786dc5bd51b7c61769cedf9fbdb53bd80bc4f3f33299958bd57c6f3493046ff66257631d56bb5c06d4b7457bdf0d2d83666b57120afe52c43a6cbbfc28ad928941ae233178106749d4ccb6a66765a27d5d46a320a646264eaf69efdb974867d9abc13f529b027d5a3219ddd7994155b20ed500a0583733f0fa23d6b39e9b82747828408b99b1eb44f8e30dfaaf5518dafb65b763bf65f651f9a3d3f3a89760d168e24dea956ab1d3aa437958b77aa2178c23fdd22e7a07d5834599e30a99f3c739cb8812348fb1cc86873ddaefce4a9d8135b435a1bcec857f72666c0a2f52a3a58655c02d1162819fbfcefa1e114d33023aba34ef8dce441febfeb210e68784ca723ff584906e26e237a582d8a965f1cb743fe06ac16c262507d44c473160d59f9966cefe38bc2b8730ab837a513a0d06b49c57df6e9d594ec495de590fc342ca322edc734a902318bba5a568f227b3e774b05d24b27be8116ca0296cb3838809778036227742c1347ad1d627e497bb6831dd29bf5d486679d3c5539492191a83004383d8be247df50dda0484dd80261315faae564b5222b5888fdf9615c9278dd4bc65200c0aae120308b7dcffc61c46bc23423b0d6e64f297677b0d240d375bd95566a9fa6990d0011c56f7d211eafce2bdedcf7f6b8a85cf616c9475eef3f7628f66c78fedaac767a15318566ce68fa57f887557d8c6c4eb70c522dbd05ccdf11a9d4984106877e1baba9905c19ca0a24bee4f24ddf439d65db31bf0e3cd0be218072d41124c5f02ea68c8e1189dd9a4592b303fcee0c8617b7b54a5d5224f2f6bbabd987a7b5c2a969e8f83a396b386e72591bdf285c20e174cc597584a04f7d6fc49bb62782587961b9931ca9f5540ccc394f29c6df07398c3e9865dde7fb3ebcb7ff0d24cb91b9fa29095f0dccc58315045bb785068f45986d6cdb61cb4741ed569a2c763a535a8ddc4487538422372da0aa6ff654fc6e45e2959d62c2a89bd8839e3974989c2c0ee8b91ae52fa2c3305ed523c5309db3", - "tests": [ - { - "tcId": 64, - "comment": "private key with s1 vector out of range", - "msg": "48656c6c6f20776f726c64", - "sig": "8e63f051515f5c2ac02364a1bcddf3c277cd953ec4c9f7a39d17bb13013fbedc2ac0f70dc50c2872766c5d2c00930c66faa4a640dccdda46a94bf476258a9b9595b3ecfbf1e47b62af98f1a9120f43428043dcecb221389621427db999c7bcb6e1da90d647f448df0a03e49166ae1aec83c353c7a88913850086139a24593ebb2b41d3a042da0bdfdeb3914f51f532bb8fecdcdebd643e08fc042f6c9f8622208c6243abfc2098ef358b9baa1e1b53cac988cd8e6dbd0bf22a7e4d61878bee666ad6fbdb6e77366994a1936b791928ac20255e48ccb69a262e2717367731ec3fa8fd47d3862429242e34707ac9b883cbf12a38aab2345cb234eeed66e4523248055317db49191cdd1754d53949cb6d008b3f1d62bd571c9152c6b259b70471bc7913601ce3be5e65957d5a1204bfe2412366f2b77e618ee648d52034cd37861795e45e9cc49dcec44256a7076efcde3b38f4913a91ed301e9c308059eb0bf0498c3cd25312b1a8dec5bf30643c19354b04bc38ab9fe5a0afa9e256c8e1eace4e37ed4a8ce0118d6e21f82cac73bdcad13fb85ed5fffff49985315ff8e220b02ad3cf1c54172172e4be54c6721bf497a3aabfbcbc5afd589ff7af251320354d03a0db0833dc0a02c5b3cad8e790df62636cc9db15cee8e30e8e5f201beace1e4a99e0eecf7a88804134446cd918017502f3decc986e16dc517f7159ce05e5243cc851954b29d0dad8c9102e73c0695b72c1b081ab62382737f129ccab0494e97788d4f24841c7e6811b1c9db8eaf156c67c3aa7a88969d4d82fbb4979e599a750679e6250dfd83ebd9a629f9cd3befdea9b923abff63be70d788a3ca9d993b5899b257dedef6d6b15bd9ccc4ff0759eb2bcc72d1cc6326a67cb50c46e9e2e4b7ed119a784fdc3207a26a446708f9e96553e1edbff96f55fc7c395993012480877445277675d9d931d46cd8afff4910ea8571c4b32c77301d45cbd37a68b47aa1c79616a71d1887041ce947b821414035cca8c3a54962a422b1326d34ba933247035fbadfef5f9ea936594cb6c184a14573f84016a5f19d047c4a03f6ad608862477f7cf047f6c02d1fd03215530e74c33f3a07d271ceff91915c8e500e296919cd72f047cd9cbc96e288c6d319afa240daff7d97a83f3ede1ade4a637e1da517ec7ee9348eb3ebfcc2b76d7802870605f3ba38480a352c0d8d5e3335e9805af9f8b050f81762b69bd13044b9c03c23d1cbf1d2557aed20b26a8a1be66cb5513661738f03cd96b4d3e439ed0b602be8dde06f95cc981c03e577c97756cb18b47c38dc473256c57bc0a19b69a794b750337b0aad55c9175014a6efb83e64f96c8e9b0626397a58d8872f1b9ccedc4e64cda696381a49ff4a6666c79eb620d41cd2660cc9a660cb3cbf13b50c5a88b0a4f5049e20df0fd325413f95b5e295698642abb3da4f36a9f9f0762eddefff88b2b74cf5dd73b08b0bb003b4a701c902bb77b034c0e86e5d50184ebc12067503fc07f238ff3e75137a68184e6798a528864f7138d563e16e46bea0ffea6f9861a7bc993b23806ed7db82683d6e04200bb3c761fde4b83bd0e7e87af3b84d527cbe537bdb6e86854161b2c6f83f7e94b1f881c5e7a68cf5f48d45ba4d3412223ecae1465d9a77fc3737a39493a254b82bf66dae7d804c3a08e8adda2ac4a6a17d309ea36d77f1252b62a3247b3bf499c2b1a6cd730d79d2000fb48c1bd0aa8500eb302b1f15d27b4467de2b8804447727d897a45f030221647658b3d1a0fca2147ad11f26efc23d5796408b683a89247f01f05dab236702418685b6a60067811e25229bcba4922af7146acd49d1aaf07c52a50ed734bf6f68807dbd3f4894337c20c0f8fead1e7570a3b7a670087089840ba3ecbe217769d73493d27110fe811d5d0c337f427e5c2dbba026c27da2e90c3fa52db1a17be7698937efa2c790832ac588c798a795a9aff9310815dc588ca5687f263ef51d7b10e8f7fd13fc6265cda461ad452fef6a1ae562abe8646b110f3bff11a4d93c7b74f9f64152a4b7c6b37f97db0a54e07d59f5f167c0a7ea7c59b1f3a3669564ce2bef3c8f98824b22f621f25e143e14fbddfd3dec51f2790802e5237b4491281e321761032f05feb90dc81902683a734f5cf3c3baaf5ce12c6c5b9f97fb5024c1a8bcd8e9410c151ca69f717d3e3b0efd0b95b5ae317db3ff8257ed1318f621ec0442783df87396bf023fe1ce2e9eb17d7dd0c4bfb845d4477c5682154b08d5395658207dbfc9b6b32f94074e7b6029ce14425bab6d667e1e36bd5302a5b03d196ec7b25921570eda6e03b9c2e915fd59a2e19cb6255b2cdfaea8395fba9efb2a447f29b33e3e6cd19a6a864de10443e8a5d98c880d6956d49e5c842384e9149018aaa01a0b3ddbc38a4e63263f6f50cf82d22e52e7fc5c0cba8843278f8cd291ee7559d7420c7e695d7d4c6feb62030aa0ec3a0ab6594feaa40fe7c93a7671891ff5710d8557f3f06278095d171cc212fe5b1e0e6811cd7e90acc5da21869fbc7063f2e8f00182f456f298b107f0a8fb045029daac643be5dbb6ded8e3eab25d323f32ec401accefa34b25e738a836cdb373dbcc953a0ffba8ca20ed0482f654e8056be57347bfd22bf27de9b497a8d52a415d03f195a29281a937f5356f72d4e23f23db9d871c50bfd4e56614b926c696a4830d5b0d081d9f8eea0f2ea0c8fecc7703324a38a70084d27644594cab09ca0252be380c02cae414be7a7cc87ad3e059769756faea339137a8d89149b3abd173f0317ff2466e905febdcf5eedd66f52c54df1b99a35b985cf35d7fd02cea2614ca65f5bc9009b3584b823ca870ffb82de07fdb9d18ff5759c6b2a1bac7f362e1992d0edeeeceda69e7d59f6a931f9e919ae1aa2a83fbf1363a8aace967d04036dc9053be669d898f2a1b89c2a7f562d443fe756575c58575c07c6094e19c55ae5d18fcb7eb2db2ed6b3b543395dadc0fe9d10d553a170f9ae03c95c0d85c2d16c94766404b08cc39602aa565faa744df1df097a05df490e13e39ddc7b3bee7104c644054b22db1520abb4e0395d4c9ce8042fa8b7b014b7c67d2f475ae4d3a5f71b914c8b7e5d2a9d139fa52da7009e82a847667ca02d50523a370d03bff9a3f9b62fc1f4a402aaacea7404bf670fdf78ef712c052657fcb1b144d3c164d0b346d02fef58c9b05cbe3ab8540e983227ec98ca4c148705158c4c6e7e72de9eee098d5ae3603a0ee3d8ebdbdf56c773eeff4194722f13cb8bd3349fea837936e42e8c29b33e516f944066f7024c682b70cd5fc7bdea41ed5414cd626086b54d7acf394270b9ce21c1264c796d5e5681171d523e13151e1b1e5d1a3a0cc785f7c70259e6f0e3430c84cb7e9feba883dd6b601f7c1d94d7a7faa4bdea19731e885b584ae526609f0a29fe6c1ae2ac46e5374d4ab405206192962e75853d0ecfb1731da85c719c9fe5d3904dfd08af1f8ff26ce00df4263cdb616531825f9fea2ae83a62ef3beb5b6f21947553b3213b3c1501bc2d74cde3cc03ad675b38f77a308b3993a7da240e5e548db2fbc19d7a16ce4c9e1db7a51b6d3afd7dfb5a1fa9798928f5bca704e6f7ba2889e385df44807f254243c35102d199fcaeef7d16d9dd10f80e4cfa27e3eb87caab11a4b73fed1412127735479dd60a94b1eb2925ad30ec55fe5c62267f13da396155591d9b8390e922ec77adbc2c8c809c0dfff0d79c598ad046af56d88302f5f3be1dec1e9531a153d170c88a9b5b16830686a30a9b3bff4696a7a6b298609424570838708b67b8a1db3613da6bbfe55567bc1da34c7de3e037880b2be4f4a30c4b1965c109606ef20efea5c0dc782721e98274c932a765056a066ed410046b1cfb228be41b2c6167f9224745af12e8bc3f67848df571f9afa80a9b6a3b0dbe9872cc70ef4b764042a9ac997dc55819386c848e103b8837c8d5394ef1ea125db5d3710a4d292e99d27a8bb015927ff87ceaf99864b0f3f50a6ccec523cf6f9573e8295aab3ae9c11abd28ad437d5895027336b6695321748b1834e5f15a0f9eae38dab69ca96fe6689ca746a55cbb9a199a44b92ab35d52f551ca1ea69819a44c5eb68b3b0f6b813c4a00b296d5197948af8fbf2dbfcff43fd7b51c128a1bc126609f3c53f5e32cd3515a899c515a42c163f0ed8f5e7d1cf7329c77b058de746b9feb94544b7cef718ee5fd3db27a11f14c2ae5767ffb866ba661479b7f0318408d65df84fea16b971cd36d07555cd538a02aa814386de06364d6acd0d885e22d084b1449bd49039f36d8e49a82af84d842c74b132b48f86856a1551cda84e9ed241670ecc005611623dd37d110ac77ef033ef52befbc5017aa5e2beb6bd21feb800884ca1661e409e03ef9c3aa081d10d792e239e9a0fb2c1378f04a57de41e62137c6c90b808d888d1fcb08b32d4d8015b0ae199b3055d0ac58b8f8b0b8a0223130e03ac7fe906693fab0e338622ec66211efd55d72f3b741e09abf78f83532004a1864baa48f8d9145c7f8e3b674428b3c382993084c9425d477e6bb154f6e7615add44922312f6fda0d16096d70725526f1fe157c93f9f7cda6f2a0fa49229714df1293ce64c549fb34a9aab919111de8d7da54b7a6f03a93f44c782557aa1c4627f2ab86d200fc4590002dfb5fd4b982b4177b86af49fb9419c88a6d2b17d228218777719c26158670618685a6b0db038fedad694116da9ca31940dcc6e7ce2482625e0416af9bd6a7617e86d012aa59982e984251c318a9d6fd38bf3029bce4ebc84ac5ab5c598353995c41c20dd5bbff4bfe3c031bc830f2b1697697cb623682443821addf03a6f257c10d3a00a814b54b5c5ebbe6461fc660041bffede9328395cd251a3b72a585fab11857e2bacd4421df035c4e2ef3936d66968e0e4ad79d79782dcdfc09e7607cf40745617401a9ba4c2403ed0d9bf54810c5aca73ee73084e60e6f1dbf5f2eb2908450eef5554e5c368518426210bed4525de60c2e732923200ff2482f4cac2cef0c3729194fcbc0bb5b0e8d867416cd045292793dddd7622e0d72b267d9bb09001c6832892fd2887bf40d93c7fb1025d427a8f3c124b015e899a26e3197f17a1b391f5262a06ff9c7d90e36e9685355a1c011a8f45fac94efa156914d6079d3b33f91bfabeb9ebe80782e4eb6e9236c6692fe902769559bc059b537d45dbea55329afebfbb4a0a40ab02a7591e2c1cb036ba2821936598a021c2596850a619dbe0f245155ef67adcd8e16ef02ab603fc30a8228ed7428534ddc39bb03bad972da439cc45fe17f7af8e5f007f2f73a7152794058309f5b6260a2005c9e08bffd464f1b6889c976e10dc3a115919ee15f62349ddc80f0ac0fa1bc07297b12e02e9c9c87dd4aa791ebc41b2b28f840c4ab4b9b6b4f20cce639dd8c724af2e60931acd0fe65afba83c8abe642c6715192d7283693406873f20b3545e2b28bcab75d13fec349628788f29bc2bb32e4d58cd75f2baa044d5c95753b680df7d2a55bb237297228360409adedb0b5b9d9e2f11a0474ff623ae58a7e36a4ebe4f2878ea66be1f291dc342002b2e037f11e5900587384a3bc5c1f95b9bd89ac1185e7b83488dcda972ea402eb241396458cce28738b51cc7f59003d1d75359a3d4ba4bce27d487878005647cb65be61d75c1ba388576a5b59b03c677fcacce54441869daa20bf2b20b9da88696632ea6a36731d9020fb35ed57cdc9d63ff0297f89083982f0ed941b5e4fe738cff0b3baa1aeef4723ccc839509b7e547e9b1cbc7c6c6cc842f9ea9da3aa942ff3066ae22ba6dcdc94811c1f877addb6a815f8eca1cd4c2aedbf4506fc0ea0513f3f429d390a3bfcb03f4ccbe13f899d1092419e8c8053fee742aca83b93bf858cd8d36aa12d0fe86583b6937d4ce1ed8cf47f0c491f19b6ff2b12e7f9c51739f7bb6c409deccc041047eeb1dfa06e4bb3521567a190252293f9198ddbe75717748f2772fb8b45b019f4bc5815021efcad3b89c697cb0df49c6f3ef154f474bf48bc2d960cfaa2e6c24aa58b50e8849ff0169698aa95fda81cdcbb9cd34fb7ca83a37feb4751a3140143f284d3d0db1995158005ff472a6c6ea70d1678715856762466bfe3fcbe4a059571e63c74829cf0174040d1ee310b0fdd6b5897988fd9e359daae489e944f216af38a45a70226e758f589b40f96d2a2c1eaa3d4df3ef74a9bbbc127f59e290ad8bc96b5984ea01fe29e8fdf3935d4f6dc4d1608e06e82d3698f6398067a5fbcc5af75047d3d65896c70b6118e15dfdaec6b5b3d204a6f7306396856dd226ca32bb19b262b1021d90fb2d5adefc60262a8bd9a2555a5c1755add5890aea6fb314beae44de9e3783e3f6f00287b051c48313d6152da76a33ab62d34bc4827e59f21818c020416395492a4ac1c20284b6f799a072a33515aa5c01440777ba0bdbee6ec358bd4dbf4022b5864838491b3bb1d515c7aa7b0fc3c5b90bd00000000000000000000000000000000000000080f161f242d3438", - "result": "valid", - "flags": [ - "ValidSignature", - "InvalidPrivateKey" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "5a04d37a8c83d373ba07da5cf96806002e3635ad8add42ce6ee9902dfc9a1f27ca9cc3712e5d8d372f72b5e2484a1566d683a94858b68bfcecd2ec128e27353bc69ede96138b633b836b3ad60aa053731d95caedd09a2ddcc7342602d0579abbbd57c9d50abca96a029852a2520ac258eadeb3420685734fbbfc38b1fe19bbb18b5a4bee715834c22f6fa89f589010949d5dd66163e995e23a48ecb28fc54756dd54fc22a940902bc4252bb5d217cb6babaf196faf4d340d5c181331320a4f641731db14111ecd8b321d22bd136353ea74016cf60acbdd4800968edc1f4fa6497e87766161c61edeb812b7d09fcfd7cfd019b447d91452907e9c3e4d8f611b218d25796c091b7ac57f0644fd0f108ff27a9c68a3a733e9ab00236c8c39c463beac5dd031719b708bb677194afb38f05d0d5aa51ee25de9a2159297555cb435b3138889a5628febdbb0d795666173a4b4f140c3e97b8f496c876e5437d14cabb9a6e9350e3b2091d600c77e2f9100a296e0884e12e8a39a9c64368136e7e7778d8ded66d1ee3bdce1e009ca29498228e9a2b4af6320a0debf1e3471e6d4778d1827c551a68a25a756505004b448304aa338843eee2463a18fc83c2ee972a140dbd5080ffe09b79860b0c0702d033e67f3111476bf58e0dd052af2cf522a0190c220270c8d0b8e765cbfffebb1fc3a03181a9a0b7f1a422b760a4e43efb9778542b011ed74abcc918ddd576eb31cc7da4d4b61115682f5e66a430a90665232152571849c3154a9b627639eb85ab5bd3ee7f01365ef1e74af28b89ab240ee20b43d388bdde1a7cb2d5bdfaa80301744f5a4c7cb2a4da23290ff1de44ceafe73028c4e504143f043955946e3b58da5f66c2e9a8367efa2905b57f0e6c02c9c918c6aa1a0f83ae38c8113f342f35a8ad2430f8fbb2858f77c20da47abdd772286655b5039834f5e7b61f1f4d59c1add1bf93f0859b7e4eaf6e39b5978ce322f0b20ffbffc87361f8f23632a5532258d7e4113a0a1e311bb7a4c6b8ef5e3b9bedf0da5fe08b2a49b255e09ac5c9e9884e0f706199214be18011cc93d845e181de208f071ce46ba663fd2e13a8bf7366054d97c6c8c2c9cc03f299927dfb127f5845a44a1e13a0c95c9287a698d5f7a10fc2c91f454ab0e58d7d7ca6790063ba3061cd324df4fdffb87e735686017357dd3535068015d8460b650680cbebfbd165bc3dffc45f441b004e71dd8e8d42e3aec09357e9a3548241423f93d775dbdbbb5eb29a29e144d2c1b3f90785e5d9f44def8fd65f1e731746d47e88914fdbe758a8a8ba731ba004141f8de1a4b4c3b757fc0697cfcfcb7e48236fea7ae12a3e279c85accf746d363b6735d6726a32f8db0ea04368917b2decb75b17332a5e3dd3e339450f83377698ec9599cb2be39d0dfb7cae50f6d58f3b8a6e4a02e4413c0c1788855e5461423c0b22febd0e5103a526a045bd051c9374d606d3738130e97fe3b91eada3c19496e44a6506f5661aba7ea1f97b52f99d7c3f08b7b250c417267ff3997f38d7d0a02bc0d7ac673213fa9e6515aa582c6808f4819a47c8f9ac02ff7ac3be61fc792b004fccff7dd2f508a2a154401d2573c3f79ca4318435d8f0bcc46e4fec20106e58d3af25642a2b8010aea39d92841fb6e9db0c2c6756c610914c9db72eded61e18a07504020b75fc469850c02c2550831918268fa0e427c389edd1a0393bdfa8233fad01528fc9edd91a10a4ab955d3ac44dfae1329b0170a5ea977623b68e46d707c71e5535ae45688e8dc44751e5e52d7c2f3d0c7216a14d3d45f1fe6e28b7191856b816ee2204092e2ac814974aa86c09f09451fe064ada03807e8306fb64912ab34b5f2f915410fc80e666bcd40ff0dce2acd1a5201c9d8ca14524edac734580b11f7054affbbda55e9dc9171c26196c88935722f780b5bd235172adc09dfc49f5fbe2427381665cdff92c2b1513c21d85c30fc6f4392e6a8f6f48f2cc474e2405569989f47cb9227db393989c88f7324b2504b9a868ad8c04eea390e4180b7b5eaf8ad028e3cc0ca6fd958f6a388cce507416f952bd05361b72329a97504855708725ecaed1c8288b1fb22a2b7aed6e2233c7c9f3e6e0d50b0f3b13f7a541c4c608c76073476ea18a3a46816b8ce867770e88fcc186a612026513b2b2d6a129758c8ba402ac85e0e21ecfcdfed34acb6444c962fb6fbb029c8a51422f4a31a200010cc1053f85d5f7833e12a8f19f497102d47325686a8c2b126a4308199879b1ef86d0ff97099fbd06377a700348a9109bc0a0dcb5cb02f728ffd996545b448d0f4ce3d1668017fd35cfcd011622f276d0f30061a62328c4f444b08d3b9b2ab3ece85881687049a39696a087196a0b6ddc483da62829d9e148f2fda9bf5651954af874b6e0121e52c2095a524c6f0804b997bec4a2b7b74f46d82742f78e327fd2c375e272e86402f3409a814c55389047df0e23742b612d545b3beebfece6c94495e3e651d74c7cc6b775e100bc9f10d68c930a72d480623be635cf47523339ad7c7efd0f234d06a5fb3bfc3e034b4eda42eba174d1f823c7390efa6b1abdc10acae3c1bd44fc20e07bb24ade438603c93ae099460d3443826cfc12d2a084999a886b2a3e76e637a8fc47c85f72bafc1718eeba5fb5a829f177d92377bc7d353ca3bb010830b5abd7cd95f5d2257b1b81befd81e8d3bb17ec9e6726b2f1b0f3b0a3c800f64a92a976efbd158085e30f7173d351a9bbfe3e0de4d9be32bfdf48ba6aacc3037aa07eaed14f2aec561d41ad680617cd61b14144c82a5aa14e0e32453c389e4237d95309a795e081300215c3813ef719b5786d06b5a3738a74e7048e7c42809f5d24764860f28da28fdb012788857804a9afa465abb237cb36e80ed11bb2f33f2ab31d461a934011f5c3fa3d8d0b9bb9950ad13d1d4fb3fdf2ce85c18e9b7689fa53e5c328dd74bde56a2a3aadc1762dd52cf0864fadbaa267ac0980c0df6c342461262e21749b395a2069eefb4d8a6be1eb72ebc16a2c7a80e56daa50c66f3efc134d1f7db426a1fa30a5aa8e0d9565ae4a4f157b21312322fe97196e3ed0164add38ad8c9818d30bb36a2857598a3224e159471aa1eab5bc00dde39cd3def50a275f90b2876435d02fb3b042c9b4fc451c4931a913158e75e2cf2f4a09cf7997dcb6888108db31500f9e3cb226382366598bff7e3bbf9b39b4f3a48c62e97e6d5ec899ada74843948a40a28f8dd11b2dccd46eb1068b84631fa2374faea3e04e65c59d387048b353d2aa9eca5fc03c1f1d615c158e2d14046bbfe6a6154a9697ad6c3c624fe580a73ba58d70e135075c4e230509af53493d9e7dda468fbafb0c1d4d9ef073d0681288cd434787f994faa6305798805471d1f29f4813fcf1cb4b8f3ccb9cfadc17c6e3fa72b678083960882c73c3ca815bb655b9c9cbc8a17f7f9895a487e46f883f8da26b9fd1749efcc8b801e85e74e010661a5ea38414a1c74f758d5c368d49426780f3821b937ead96deeecca4ebec92cc15973f82016a86736009df0fd484840217fae26d87c94b0133c4bf51b7306571c23934ed4401b54fc2bdbe1bdac4a8e208c40e6881192bb81c315750c867076bf0dcab552975f0fa133b80cb1fc0ff26ad7cd80875e0c2d61", - "tests": [ - { - "tcId": 65, - "comment": "private key with s2 vector out of range", - "msg": "48656c6c6f20776f726c64", - "sig": "144e64c23792b23bd7d66cabedd4a01b140160ff60a4751f87138c93f38deb79ce71b94eaaac45c740865b247f22f8d7d7916076b48e5ed98ed9d29dfbcb54eca509dedaace575c084de4a643b3c739021055ae9cafa367c546d1721b3c96ed22b561fa0c67b2bcc2c9a1b968d7a1a2ba09c754e9ab5c7bd5bbedbb096bf3c531bc56caa1400f6ec2afb735b5dbb267469e4ca9ba503ec8b9fdc66a0d7d4c92a7b8fb31e1adfad2fefbaa52ff11d1f94e3af36584c9ec3f872c5f35936071e3972205d40a2c8556ff4da54fd3605d399f96e724634cfe802fb47847271981aba3067aa25a81996140b13e2ed1bcb9648a6f256f9bffb9ae61b689586a6dea909f5395af4c794e845c456c77012ef9b880380827ba45b57da2885f34752525392b62f7c7d2c72c40337f9d7dc91536500d9930ed9750469c17541908abfe766b36e1f7553104cde510e01e3ee5991bdb0b3bae1cb1917481db5dfcc4fc6778f5ae5fd9d1b13fb514e9f61c2930d97cb28b3c3cead40dad0819361f9b8116b94e7df5ab554295c3212e7c1cbee556ffb739ec8667c736098538690f307978912c0ea9d95b457962cdb1e025cf4e67a6980f07844b6f7f2dfc752314e513c7aeeb16878978a95a3171ad609132c3838154231164ed84a70020c7868464467a03b36aa41ec657a6ee2b3752c129a1baa5f5d47872a3a7235ad1ee599e21bb776f04e227ac16849bbb28789413627e81316f842a1811cfbaaadbecab6810aff515127f3502d7dcd6dbd1e2e6aca70950318f3e549b007e611a52693de587020d1a97b00f0f41e968e2a17e9a445b410a70c1459ec5f62947922c58fa45196556ef563533e51eb1531dbfdc90ce65f6feb27f1c5adfcf2fee0f8865205d7c811266836633a73300d58cb2c41698b41c9c7c4308e8811ce4ec01b008306b4198b2bd51ac68ef63f7ba8f4fe8f359034df4e6268415661b5c9857eb0b076b96d55bb3be25473008ae57e4947fb44b479c7037a8ec6552a71b88fd18794805e554a7983928d72a38713ff0e07a35065eb73b9b409a0c7bde333b65b0f1d8abb18ddacb584e05c70e874d6719e72d7f27c9d6082dd227dc1eb696109711611a2d7fa8e21e205486ccd9899c326c61c34823aa0e3616cdd15bbff7d77ad8b0e66609cd03f41b3d199aaf48a3fbc2cfced14946f77a89abc069f95ad1cd1055d8abbcfa859ec02eac92d04561792035d46337cd060730dfbe53cc1cede816d557ead34dd23e5df6cafa38cdb1a3a23647b3b1d6e7fb061d46fe95ccbf4f56005274b32b213710828f5d2ed49aca29629228f65db063bd454308b8ec5d3fe4472fec8a0d1f68b7697f42c9bd24eb37f50309dacd2d8ae7700ab4be604b1eb872c42b2ce8d52b3fd14d5115b95599f719c35551a8d4efda19a052c38b46967c21b6b7f4e2501737fe131fe58630256e2b85493cb162245dcd4a68265026e9eb54fc3e9aa1e5c5ae67d1fad3a43bea44b3c019a616e96f077a522a052d51fab0e853b965f1f6db1e47675dff08696093bb42e7ef008a028fffc55a2ffa59d2bc9427c336589b7347200ddb6f5bf0cc9392d5e018a72092d2f1496955997983d418222dbcfb0a5ec2c509de26631cced7bf5cf4f2bc1e29d1bb7db0691ab0f2c46dfbe24c15d98a58ec201273faf6f8e2005238a5d41a9b28ef57dc6bc31adfe93df00d0dbba25d6ce9fd0fe55f1c219ae424c8fe9c0edc80b7b822dcc4514537c59ebcfa0c63d0a733d2be3c71ae915ac6f7a54bb7e69181e37865105d9e7d5285dc68a293acaa1603802db88c0eff6b0e5b6bdd416accb4561bebada0e86d21cc751a73e55eb718cc41a837969dc1dde6419b2a1fd8d0245627aef2e708e9d46f48261d3075739e1528b683dd509947b924267453192c622ab3a7f18732f1efa42735d548a32305adc0f883c87a607af75ef8830b1c5a822daaa140ca9334d251c9b7d3f66aa8dcb6763cdeffad3fd8801ea8623d58f787290091c03ab8208570905c768d8b5e84cad138c54167074fda4a0fa0a1a2e1c75ac5194feaca1486af0a97ee883f367ee4e9957a11dfd6a798148a2ee9b0e7cf08a1ad228b130f293bb08157dea95a2740f13ea5bf96d9bea01d90f131b3ebfc5a736618628fc5ff153e72601ad6f7456b61383ff8046aa52939a6c420965a4652d9e5bab233440dd8a0919987b3d8d1603552806beba6c5c0ce795976c33c502bf46a8d520ed41d9f509517d23e191dbb243428d7e9a4c47ef4f95acc6654f256532fcf35d5d527e24d6b5404dbfd167e0f56a7db83edb46c928346c6520ac0889802c5a94bbd0156a6be9a2db17cc32a982bc3d8940d7efa3b1a7501797a7d17ec027209aa3ec0cfe3fdf65fc7f9794d0533ffc13b74fa427044b64fee3e6e1c3d7a03d228c2d88416bd669cf3549dee4a0cd31378943670aec344be3d40521a711b273ac43e14bd2c46cd150637000ea1d6ecc729ff4639fd5d422a3cf95f051e651ac2957479abb6d2bcde0b8387a04f79d7294cc5a222a8971e9b797154b63653c70c9fa68571d58be2dd1a8bd29108ed4b3d4890db7db62ee2a888e97e2e69299f23eb3900742ac69c751d6d99bfcdf1506e03679d7cd3244fecf6249ee38a5cce6b8e05fd8ad163a5eeb3325744b1e98dbd8fe94275ea61df3908d81679354ac71bcbf3ab48e8a29b809fa3049f8936b80d0aa0f9c9df786ec459b0aef9165b60c45c790a4e286c88a9f8ed298666f81544f0c83c4d15d87c84c39cc2df58bdf83f39aaea0fa1b20e9722ecc5c9e7b6ca308bbc2ac8baca17d2167ccbbe4fb245c3f645766817aafb68899ec9aea571b0923309cb33a58624f9fbdcc718c944aa6631959aff0cca41cfc60c3d202877e1b7a5eb263104f55c124e00e4bfc7c760fac2bb6cc8a4fdbcfc5cd458f6365440c144bf352a4f5dacd31b32a7e931b06ffca0257d70c54bd64d63f1de85e66dcbcb19286a2707c13bef433c3c6ad2937d2c1ae3cc754cb8f77ef16be18d464a2eed61f7e23e4a51407502eb9b13b0f0e408197930280a7226ab63e8e5d5de169880fdbf105dba6950069553dcd6a32f97a47790eacb75a436daa16e451cc441df87a0cb4955031191eaada254579795704df06ebd23e6c27cd5a460a23186a14dfc08fe27bd774df1c6e44d9f45bc492ae651d1ed67816d1f61afe39c62a68180a58cf687edb0772179c2f8c7f4e347f139c52a8b4bc59d8422ee6b3915023ac035127490d5201ed5e3ba1d617e459a3a3a5bfe6746dd80c9364046acac6ca946667195e89091e6df163461595fbbb3f9c2bf165aa991b582d28d0dd3b9e44f55a6064a49524d431752ac87ef3b5c05c00169fa225d813befeb34fc4cae6a4b122f718dbb009e6ddf8dc5a89aa7bcfe67240f0ce25bf5fc39bda6072a4f9c66289808d46430bddd15fcd8e6217c562cea1c58301d0a2a71c72c8852bf9cbacf8a2ffd4c86ceea8e81649845dd0065a750bf8eec5c2443efd205f1d79dc3e89a019fdddcdafb0ac6fc378889742c56fd86ad0ef8a9e1b86a936bc13e5cb948bb6d83c16ba3256093c44c27039563dae41de74845ebbd57006944205ebf37a86f0de01a24496f49487339493ded96817b7eb6cbef77985d185477ec9b3af879d3b4d7dcc43dda2435b0281008ede10f4fe0a8341b3ba63499f5a3d42b7d39643cf78acdbbe0399612d4e4b0ba9711a2c69a83fc3cab0f37aa6dac8e242eb48d81c22556bcf296d04ed65ce77f14b6185979050e5e6f62b976a69d580fb420208a8a1534653829ec3d323c0b418160bf08b6eff7e73e34cd498d0b5aa6a8a785ad70bf62b077b189c2c011bd7ebd82d646e9769f5b04433ab7b0bbe956c755bbdab082fbb846e87d4931f398e2d0ca7b93e0ee41ecf0fdc28c92960f8f796db1fd6e41cefefb0e6d34fd23e126dab4c53e66792345b1fa48a748d0a08f67adad9d0a5864b0e919199c0369cfdff8f2eb6749da4e9eefe8535857b57d0994dfaa0b4d0496b8178c760d9adbb7ce599d51ae0a22d1e05873d446f2f2d8b1a76f6d9c746ac369aa1fdb981f979d2d654077d411b44d4ab56537c78b18c65b85f117f45cf9ca51793d4f39559b0cad1225dcde0cbfdc990585640353b361aa390dfa5265c97ddf0c2faff99d9ebb89671d857dcd7931507a204fb0145731c7565f0aa017f65d62d8ec3d5a3305ae7752e173b256bfdc8539a19e039355f343a11f137b23807ef7be9ca912ca198581e75f1a752e854d8c4a5bb1a76a53657cf89478e0bec44b31ff864217b3de9b418c37c11fb15e821995859a2cb2c4c1ead8c8444b71d01558af214ad8101b241cd8b58909b693d60bdf657780a49dd259818cd577ec8bde5d7ea39898bf159d3a6014a6f2b56903c06b305434e5aaab804bf92e944cece174cebe2506222a34d0ba9438dc8ed2fea3e8706553ef0c22b8b7306872953812bd57ac5a872d7d27e61fb9610e6d5cdc49dfa7960cbd2cc217600ad94312eb12fe5e3c3810d0aa114b1ce0ae64ef0a707d468ee0ddca40c3987a743e5e317f23b2fc7f8197ab5084c9e20cd294539586e5299cac1afaf26fe9e5cad9bc80c7bf5b5b1ca198414ca9da2d4202a92bca8bf8079e6570d24f9b3de0bae69bd7643916bb0b700c14c52dc10609deac016e6a40c253754203350ead19cbbeb75bbea7da178bec54037bd86de347430f5fa7bb6ec48478486f927a5643b1722139c397775bc0803396a966df78e8e56082707497a732cd33480fa816c1bad9e63d5915ca2f0c1bfd162cd8bc3368e433e96760a3721f7e26cdbc31f86828e265a5beadc1dce0bf4a4d563bf9def64b985a4f018324267a3c673332f91c0d6fa84c4407f24e27e8ff254c1c55ed38ee0d688653507beccdfce2a062d063e92f6899c8b4940d6db3d08ff0f061c3eab581289d5c2becf421a77131fb5c07fc3cb4819df6d1f4a5dcce0af70a58ce7bc5ebca698f0a3fa32386e30bc4590feb619a768277782d87c2fe8b91b6caae6d64e63194a7a8903717951d1c24c41fa8a2b2ae161db8ea951d7de960ea222a2ffed8a7ba177b6fb14ca7f91e6f15a609669103e964249a300d21ff514ac5eeb377064a2c153deef006ad37af1cc9f76a2125d88fd16c4e689b05707b158edec2daa943855724b68a6886e0cc9d95ada4a5bdc737661e88657eb2d7a98b555b183b614b4cae7feffee0959b2d914178bb0634361bd756c71613e4e72680e1a3f89ba113c70ecabb3a9ad443a1696a579e7623b9b4aab17d9f56c5c195937639b33c4750b2b0b3275c1b646529c77c84e07508115da1979dca4c565417c10fb6974eba59527c0e20db9a9698f984525552ce54bac3b4f48a4b4ce07c549a7869f4daac52d7b03d6196df3cd504692d1ae2670a9c4f57011c982788f0e73cafd714eb161b395e86ea18f3f1300ff2c4b4d23311dfcd7dbfd42e40f1598618f1d75da05956a354ddceef6775f47edd65efce92b0cf427602e06def96ae7d920f050ebd1b7c02b5fec8ea1278850dc8770d7c83ac04c035a289953e944a601b3a23c01726a61193569c12f3e0aba93d88bda96ab5b67d7c7549ac7aa09142ddd74c3bd47e02d527007c56d4a81f211a7881f6925579721c13759e117e5d2e11f0f7cfa9f13eb1005ea5a17349c5b9a0910b708e0dbbf240f8e397714d5d1660bb62fb49838767451ae3f59cc5a00d66e6b6aeb8b6329ab0831ae1857d4d3d4905fb418ead8d6929820cfd023ee383f0646784b833565c82e26c447c53a088a56abaffd16f0b4b41793bcae935b83e854efac02c225ce56c9f6fe7e246240e22e263206f58b49654a5d23983c44be271cf5e5232a7fef5d43dd6c08b0547fbae19d78d31a2e26f1200521795097647f99738dc1312636b3db84851075f1357dff73216c03dc0831dd32bba671cd05943b7b963b9d823d2aa343bb0885aea4c8602d6efd30224920607d73d2faf03f9c8f875759ab970a8adedd3e98e5e869116ca1a587389b0e73889180ee325d1548f7cef1b6bc40d4497c1beac361b4543a5f31c00e1db11dbd9719417b8b14e744083458a4508dd803f8ccc0e0c754b96187db34d6b6d33ac499f5723d2b527dabd9d2fb2fe1a70b1fc509333361ff50ec829c99b73b79923418bc23fd61d975b720f4a810c5b2a55388b5e63990512b6eae6e6da7fb72f625295dc4ada2585538e4e22ea905967e19a9f72dae048c3636007dc704a1bb3d634f0729b1f23c52a336ea3c79523478020b48fe4544d64158546058429c835931ff9071c380b7a4be1005536fe9d05b0951e4826464c93a662b5b1cb6b6a5fb3d66bddc7c7758d9323c81ecdceb4a876bacdbae1636e041efd2039dfe4e4d276ad1f9057a0d68d1f909470c151e36384a4c738bc813152a319bbfdcee08091c9aa3ad1f23415a646976c5e4e9f71f476f7fbff81b54688f9eb1d4f1f9185a70b1c0cb16184d98c600000000000000000000000000000a1218232932383d", - "result": "valid", - "flags": [ - "ValidSignature", - "InvalidPrivateKey" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "tests": [ - { - "tcId": 66, - "comment": "public key with t1 component set to zero", - "msg": "48656c6c6f20776f726c64", - "sig": "826756caec6c900c71090aa3c0611e417923ebb49d5a8914f06b970de569f77774d589ab6176dfeaa62f0aca7c83642c797586cc4c391dcf79f9a0f45a8f6ef2000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "result": "valid", - "flags": [ - "ValidSignature", - "ZeroPublicKey" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "2b10369a479b4fb16303a28768681ba355d73772526452482265f3d72e255bf922375ed19f6aa6168cb0ce20db1316cb3f19b9fa3f68ee2a48419c0c496f4454e4dbacba565db639a8ec5101c632f75824da76cae773d246982639537d9a3ab16da680439f05ac21d5e6417fbff4eecf5a3c53f43be5df50225119196b68a4da757538d012053f12c32d04564cf4284d721d6aafe3835651578df1ea2e7899d7763e2cdcc058d929b8ed98f4a3d8501172dfd76c1feda4ebedfc324d9974482736985bd592c3f5aca0576f898b896e781f6c58b9c0ca335c697340bb6451b0d758174bd01a3a1d49c6046f27177da394e105f8c5a34cc4fe6fc7eaf0641c580aacea6e1fffa6446e18cc670fcab73efb7dffd731ade558e03b6f64a47d0f95377a39d41a1c023472b821e88b0a3b18f2285b11d160b380b6074f41b76c5feb04284b27921fa7ae7ea8d9fc0ec529222f73876ad46054f56058fd5db782004a96e6067f523bc8b4b05c3bc9596e0fb8b564be7f337fdc3511af3371bdea9fc6d760ad1b2bb466016ff4d12898ce215e48947cededc6295b295b83f53a200bfa08f506259e969fcb80b8fc1345cc6a7f6e7914876afe25d0a25f3268a652f3ca73d6030d7638a9b877b189d813f0b9bf64e324ce99e274a17c3b83f3734c1387ee449d1fca68a9f38d09ee64bcd02b6df461f732763358803aaf24150653b63ab4aa12c8fce4941318ade37892a227e4cc60fb7aed01b68d6c1ce6a457e6914f03f6cf6d5948ef42efa50353325caa52f221bd3d53c50bdeb59c7b0ab371cddd9a6e09834b7b92f67710c28e1706eae8678cd058bf6aa784d5b77a6491ac38da42179c90ac63161ce932372a73ccd9a6e3a60380399b4891501e5059ddc9b3e822286296d63d9480891392eaf81d43c67f67b5f0cb56b1104df0b61a8818a1c41ebf664b52b04bc8c9d9280c9ce12563069f48f95fb2d2edf5522c5f55919e32213c2f4a4c0e165e4497b5233d5aab4d47a8fd33f55dc828e2f24333532c999511056bc41a73f19e61b52768bfc5b15e22c8449389db0e98c0ebe90fafa4f95726c90a0b387b59ec4bac27679ef3d729df11ac900eb75ebb8d56638488d91d4dd7a97e16de43663ea8a01807ddbfbb12b03031c65739f9bd04ec53d2e9192becd7a4baec548ffe17db73e58cdb7b4358575badcf37ba7fa3cd24a86f9efce167c7d5adca874bc1014da103c4301afec0b8a1020f8cff394446518ff9b7e33ae053b76bf58eed7ad86ce7793003d23f814bdf8aa773ba1a5ffb558cb4f94eeb5831fd247610e38fb8c10273636a811ff53cbfe530e7c8bc7f675d923b073b4ad57437ef7bfcd51c9e4f0faad819f1a2dfdc02fe89ee9c00cbaef55b3fc0794dcc36c591aa8ab9e9a895d6e635a6d274b1cfb830b4adf0dfd3db042f1d94f60e57c1aa33fe43feaf753c67ad38acb6df2e9ba9d66e1044f5d036f043259850c0fc5adf3a767081712445b2728c80671955a78dcc60b1447cc58ad187bdee8c9d28ce6c82d9f4e9fd3e66ce151da171ddc62634e176fd59d2b63e27ecfdd712a73a0dc72c51f84ed565ccc4e69924074560f4d53babb74bf8c072fb4221fee6cfccf4ed7d8195958d572a896b5b8c467969030be44554f4b5544eced8f4acdcdc3d658aaf45a6b0a3f248972a91d95f2618d878164334c7e84970392ecaf9df24d603d0330520ad65c919c7c7356461e11d2cfaae60c29b38b04c64409b16fb164799350d35b361e2461bd23e9922bd7ea7129b13919915ade91c09f9412a256a860c8435dc62842ef0454133f1d0f4ec22224f556f81876fa46859adbcfe84c70b1656cf72c030cbf0c079796fc384572fda0fc504aaf3de33b6a7aaa306254817f2c208706daf191bca5aa107540031518f6a4d37f1aae6dd29469fe863e92adede2c4d7879c6b214a23f1b9de2f6a9a4e90af50e9b4b671a7ef2635ad2fedaa5dd778813246468bde9ce4cb2cb9e5f23dfc1ce2e004bc86a6ff41bfebdfae33ddfabe5c8e4224977bdaaf93a42286c0d14e2603fdaf50557422c74238d2ace9d269c595d6d558ed10406738697dd42fbdb2dc49dcf8f7e96ce801702629d8a1cc503472c2254721553ffaeef3762c20cd7763d4f4b9daa638d49614496567c407aa4a9d225b5a94c53d1069f8a8ad3115344d46436466a6908a9ede7c9c747c607702701efe7cf633813da791e59ac99d480a1bf520163fb38e61d0d8f4213294937cd34d55441f20e3a1692bc84ac09b89ec126ed825c565aa41de3f77e6e7156af27fc5b23059dd33bc173d3a3c15d98749ad1b25b7bd55c188f094dad04394067468a6c3ac53aaaf6131f0acdf00c677d015159a7a52b898d8485089c46725628dec68ac3e906c7d6cb7f790491c1b96de5b0be9e898b9f839db229bc6ea68eb9f8ab8e22b97989be72972c13ebdc86a7d4b78a1c7654efb0cf9b6da170829361f3f7b003fb4f184b416b81c9ddaa4864b8cf4ad1888d8c7238a4b691cd9fdde48de695cb33344e94ccf39db94943c2018f891dc020f19efa18f4dfebd26f7cdaf5a925bba6f0a8d4d203f8a8e295ac839e861a4f4f2994e9af01fc7aebfcfd90182c47b52a832625eb3576775bf61002e86ce25e20c1ce951bc6cf08aa2a610c0342211af22eee019736cf870e2402e0bdb386a5e43d71415765a5e034a3e297221334526884c6ce9ce0a19526e1386324076cb535fb946e1313dd2225546ab7882b5cab051798299928aa8bb97c4eac54c8a43571a109a283679f33c09ac831cabe30df2ccb6c7826aaf021de8a6239b67e09ff9e0fa7be5e4557900f028ff57b72d3c1c9772833e7df7ad57736d2d4dd2e8e764907aed844fd7ff3846e4b224569791501523ddb71d50ff1f63b0a82e4355c79a807811400737fa5dd578937e771a5228a6f6324e6f3fbab79b59bebd5fd177e48ae200ecb2e2cdbbecef59137d048945303dade96a59c8761d12f42dec90d6e696fcccdad86b6cbb46154b47e86b55071048222b0c2a15e1a66718f012d857f57c2c873f819dd7e36ab9b809aa64f79df3291b90e13e351ed1c608f2820fd8353724865b77269e3ba64603add9a997b71df6b3891feb30c3f7fa68cd6d02298b360d09fcf7e5604a167dc5329236af4374c848b9e1f4eda6823a83fa331f2828a747063070dc0bfa63203211479d09cd5a6002be5d3fe369fdb5ebc437ced91c85fa8825272b1d4855d9edf4ce164c7845374113ff8807bdd87d755b73ef11544e2dc90fc27541143873cbc7dd254bfdb75b8611c397f6955c9fc70179be2384fbff20e2c579b9f6dd09081719d44e3d139d96e82abbd6dbbbbc654ca4e8d6d0d45c46a4b2f98a82e9f4871e013b1181a385ec6fac634139a728e6a806cbce4309e7b27fe0c0a85f6644bade00a1e2ab561396281dbbc0648e1fb214c265550467230066306060c6c549e34096df939006907e0e38140cc3767fec01380b45794d9f23c2f88d471bb5a7e151760d55f9582ebb71d0c202c6b37d1fd0649aad3c1207c43650eddb8acabddf5025b6549b166e93899cd27982476ec3ebb1da4cfb9e7e65aaea120bfcb9ce455679475432383d96708a70f534ff930d3352b614a294ab89c36466513f8ce4e", - "tests": [ - { - "tcId": 67, - "comment": "rej_ntt_poly (sample_uniform) requires 5 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "a7d7afe9fd91470612d6855fdf0776ab66c0157e00f45344ae5b4071effb517c20e417987ab3692ed9ed90c89b76fef1944391a6f1661cc44e882f82fd6e7a1cc828e93e0c9d7af99798422b3eabb4d221032c61790c29cf219c9509b9a03e637ae4c9111c88416b0c74acba9718c0824ef09887e00f32a596d4221d996344da98933cfe2fc858e3605b3d0346f9c9e03ce2892be2abda3e3057e6ba784ef28ed17e482a78e44b0064ebb03c1c1d0b94370e1d4bca2004afde50f5a8e76cedc1ed228666fef0d8226499a104f3176785e7484cfa13f61fbba0e24138b7ff38f851615591fdbfb80a5eea112ce977bbe90c747a654f589790397e5795fe49111a0f615486093a0913600df83c18c774a6eadbf9d582bbb468c4044e7891cc9510d790c53de923e3e78d1ed8c4a175f55b0b8db7c30077c0a76cfe206414170fadce56996b758882ee017303026fe7b20b64a159f39c6d7a43df35a10c13d8de74d236ea48e6ed08d53e96bcce6003a47c787b3b87940038ef5ab45d271c91586fc2c85c861874b7ce4f4a78d75555e34afa15a7ffcd252fe680f90dd595838b6df1c4e782d5533697efc898ca65638729a228da5d1d0b5c5658db4ad37918e006e60902407927539b2f9698218bd73e6e919743937da3bf23c6cae013064c50a71e9308ed3d1b6d595cb01b48445dc2183dab8d803f56fd88dd0eb4095c347e7c176807ad88e5de070f594b5ddca726a61fc95ae903a6a3416edfbeeef9416e6e59228b9ddb3d7b81ea5e402e4106182c8440b185ab402d2f585998edc0271b7750267dfc720b339aed5196f502e79456450b586f98f8ebfb7383ab68cec191d8dc53470cefcb6889c4062a0ab6f095c32366d56ff8d414f9b6d56d01f617638e44999bccb19378b295a78e68ad554e7cdf49ccd9fb9f582c46ae311f8de213db52074c9ad47dac1467506568d2ad2c50bdcae27a04ef2df25479e31ea3880e96588b3efb3a60aec2acbcec0fd2fde673e5f7c6a71ac958d3767152d8e7e2c206c97e059ec180d401a525314cbd2fdd902072f80a219817277b2788c21bb30ec340b7fb52c85dd5479284a2565e600ecee81df819e849265a738a156583732fc47d84e4fab298707df53776d6af160761b1563d9da8bff9a5bace5418f3e171b244c95a4a079c405613346ae035fccd8b7a9614c13b51314fa31ad47be50f666b18c636f6be3b4cb45a6286a002b7f73b5348cfb046b87599b03fc440e3afc138246348669552dc2af75174a1a00a06f8ed5df8a710b2c5ed2e5b97a75b8569b8cc76dffa6f16587f45006c3a4b0cc97c0afe88e31cbc67dde34f76a3a116d359187f39691ea49502f15fd302b43c9456f2075194fbed22120cc86f616b6d0a430464bbd0508a1b7014a2059f8be6679507c995629627f88154b401131d190bd603c84f487f01dad21240e8e3aa95c05998b771f9e7c4a719a1daa4b91e0a301904c2b0c94e7c6805e6f28b0c8adfe8d47e7f2978d1eb59fba567195b81e8191ccba6de77f19a16a3aa30d67955fc94b2b0a266da4b625a389f592f8b951bcfe5db743b1e81fb94373fb072d808e6f0e5893655d96933bb540ebeff179aa9fa98f36cb4c6a78e170dc859b753fdf9a51f50fa0b25fcaf25e1b31aeca1f3c4c024fdae36fa70d8cf3b8399c17f866bf2c33f0db659c9cb464a323904fc6e00cfd1a2cbf847bfa428d00c13d8ed229f56ff016ddd229b2de2727aa048b972359940ce72f88f4326b3570e4bb621fd5327b59abe425f3c7f547f283b7865e127e5cab181667141e810f6438da61583e9f702098f08235a6a80f1d9350e6ad4239cda1901637f60d1a8454d85399d324e3cf538be98649aa2572045d8c13fc1452b5ad60dd3b0ec35bd153aae1b56c48bee037d7027518136d06b4914b473f0de7e680b73692c652fb7db3a38159d9f1159e8df08e8352e8336e823a2dce3ec5cfac60ef625f7dceecd78cc21b6895c7c9dc858315fa0146aab6fb27ce8fd18eeee354dab50bf4b70e0a2eb9b11fc83701fcfaca9e5cb11ae3a76f05de2f9b2209d55062c75b06ddebb32b9972aeb240c98d31bbd31bfc0a86ed5c3f693e7c355604260b32712a6ec0db6d021d29f842d11da7feb1927d5f0eda6f7aea8e4f3781a437a28e9748610fefb3abaa22a6fcf2003552b0fdc320cb2cf62ae8fb64ad51ed175a9d216a0b044eb5c32dca5e9f4f98ab4e0b95b2f6af4028f2e2f1ebaa7efc010044413da811876d9b8356db1e6735e7d463a0335f6afa04ca6de1a7903f27b823cc271e6372da745bfedcf0b5bb0e18adfd9d4233d0fcd05ab8d79be0a7eb11f1ce2a7e052251cfad1ca90b5e4374ccf1a129ebaebf01cdd8d4ce61aa9f3c0796e9bedb5502d0e099c7ca15470765edb69795f0d73cfcac91df6f134e5d11e7d2e3b5c8ae8387a1994b21402d93d65ad72bafaac8932a9a3d2efc87dc68468ddc1b3c0c1f5013e10479a162c442af0374383d27126aab8b78808fc7ab84e6881fa83fc55ea78aaefa9ecd526d47e59cca876d7e7865575d3100a871bd9c3d17a22ef6bb94bf72b9cdb11f6c9c66a7849df8ac2519abde05bb728df9a94220c0dd10fd1bc7cd4a4f65a55ef47d7b9d63f9224216c82edfb171a76a06ef29ea233e6692101b7e0d648b107d2fd616a564543b8d42e74c5a2d05dc1dbbb8a1aa04fd5acca120ac80cade80ceea66a998e4efcde47a2d440d31348afe85eae79ec9cc7818be885f2fab618ada1d2f1fcce920e7ff318580586b4f775fe8648629377551ebda731d493b54b16bb19461bc484b23a673c152c0a9894e71d534b072a3721fe73bf69562539fe5e0ec82c62c13dad89d9666efd6df4c40e7083b5d507827bdca7dcf218bc854f2f66060826645446c6279408351c3bcd87bfa12e9ba3dd1b7f36f97bf2b0c3517fac191e40ae4edb5fad23b390596bcf8baf6280bb8d6a6a12a5b25127768a5b0c6d5294b41b2b8e19ce6826761332dbb634243ca7edcbbed12668157445e0ad5ddb8daed13d37c5e0f0298d39c1d484bc0bd8e2d2abda428c28bee13381b5d6938d512ba72de3cdce6d9b14d71f7e214ea49ecbe14b7ac81342d38d81647f284a1d363f44a5114ed53ce4fb57556509e6bf52f7f5ad57536803df6ab6e3192f3d5cd855ea68dab4fee624b570827e0c5009870f114d7aab9984e15944ffe95ceddb693e8cb267a9ab46cef54bac2f8f36db7a4a4c3aca9d67cad76b44eec0dc72ce535a8b0449ebce056024101c787732a41d23fc0d611bb8967ee3187a85ffae3c134237bc5a1ad2d8f8a3158610fdae45d0831cb28758eb4d28e2c71031342b44580110041346e697ef0329afd7cad7fbd7712c44b13694cdaccc59676137fc2d33517f13263696333850c72281c8a8877bafc82879c3a3ce307a4ae70bbfa6aec20d6ddf8c33a7e242d9e69256321803280be75a0196f00bc3cecce1c9a8ec07acc47cd23f356f37606f2356f499067a2ebff92c9d68c4f377bb69997953df1f244baa8a39f63ea389d307a04be4fdf7aed763dfc0c611665a4176f4a7f5c577795e500e0528ad304680dd866e3b887e2bb13f089df36a75416597b2b6de3e3f22e36ed44f5474a5e74f28a255a4ec6914a9226147a1bf67d901e8b11cd129740da02bc3319d02a4cdcc5ed8a7fbb2f156d7e067abd1e0df6a7c563429444b0a08762a964159c878f762fc460198242b119c995cb4d7cda51d9d262636c2894ca38ff95ef6fe48d543898d2ffc31e0dd87c00933bcff60232dd02c2b886d603fa587cd7dd8195a3d119bdedf2203c9dc298e1d50a0dfa4bcd10ad1aba9b047a653cc05ef4dc289d3612e59cc4e12a8d639825f4d02737ee63f1ef73902c49658c668ef38cd233012d7793ee215ea370bad665cc322908ac1a9205f7fec356436f0a6c0db616239b7b765123445682cf1595eafd3f9fe3022aeac0ce2e6ab691b89ca88dbb2f5cc599a933972eb5f76e0157e834604447d3bf79cc773930f2e6899d211b5ec72d045e557a82a3d0e5ba23ac77899979d2dba338f5d9dc049628f433396956260e53417f37b8ebde992246fe45d95e1284b0b1a2e927499a6f180171086f3549e12a2dfae7a54f4331e4e4f38eea863173a565f8dc4de9551da854c2f48397291230598bb1c82ac56fa01a0f5ec16e603c12fa45a998380c08d2f3778236339f2970a5cc78baf8fbc784fa1f6c88af0bfdf42627b4671b9b1024d06743048f5f3db053ec770be4c7924c87f948153138c726d6ed40d174c22af74a852cb28caa6ca74b67e5403d34c21821f70102e73cd65643e08036158c805ccab703a528dfcdd1bc58593fc5dd382b91491aa860d8ca204010cb3446fcc97b5dc1058109aa5e8b685658969ebebb521580e95b45fc733f257f80ee29acbeae96a1c82016fd5dca8ba3e37eb4ed6dd95c254d12199bf3104dd801fc9d34b8e6d9dbbc63d7fcf7e5851bbf666cf303e1a53e5711e5c5804ea92004f3591fbe9bf612478896ab042036315e447b00b5df1ebc5151c4f4d619b12e6769f79fb31f1cf6ae63550230b2cc4b6d975134faf9aa41c5da0a5913a78cd6f765d5a6bb5e3422ea98bd5d2c255b4a27d8aaafecbbe2d42801047679f4fed4d94b71ea8b44644a1abb434155eeca0e2a845e673162b205e6bf1b5f32f78dd0f1163a30f3f6c44588f339a11b62eead81f84aee14815d54979bb29fac6d95f3a329805b1cc9807f694ec9ce6c9be7bb85248ee7b87c0a5f9c186e4517fe48d59fe4da31d2a2691a21d056754390a04e6036adcc20b0e6ecce962ef86831236e96c0880564bcff60c0848f0fe351756f705beee4971907b77ed08a875494d6e9d230b8ef81820d698c361e6e0d242dce7a79c48b316cf0ba4a3970d1dd9a9a5c4ec3545e7781091ef5f78e143e3a0a4aa82b572d8acded5b6b18eaa07cb843ca7614a9aaaed2fc97e675d3f3436ce7c29b5905e20b7635ad6c1005018ad8edffcdb7c78a71ede3ba9f5a6b63f17881530395afc6518774b2b21cccdc91b096cc294e323fc2a02a3255c96079bca232ce2cf39b46c73b8a2f3c988a264e4b783c2ca30780a86be394c0b4a467be4aedad4c2c5f77fd8fca6b40500c597cdbcb20714dfae8897b788d6c7377ebac29da41b4f602cab6169a80f6ded9c57ab422a17f6115437f7732377378543408957e0a08cb5e0332e5d7f24f5a6e1ff5f2ba37596c851ffd47a28900497985ea6e06bdd6a62f621d7307d79a9e0caf9c5b576427c1b0a7dc5ba2a919c6d8deeeedbc6785fc4239ff24c82d3f8467738888c9c0f1bde66ccc1a42fdbb55001cb1eaa024d7e1e8a8a8b9d2485a2854c036d4ac100aa631ac4913d2a4682366562929b36b9eb3b8e67261149171b43daab34bb4b6cf17e5444c22a157d2d556457fc82bad151b3e63d0fa4a7395898b054f3188383145502023ce889fe1a3e4b2393c992ca2686ac3de193de0e62f22ffa2db0748d1706e5a9215c9f51405ce30c265b898dc516a2cc4e216a803ff9fdabcd97b21b26dcc4c438804627cadc7146b222f520f0537d5d405085502e6acc498cf67e2f3fdb525480ced94b8d3bf63b677fae897a555ba99314f4fb02831ef82c6c9eaab8ed392a7e48db1f8d1cfc4a243d3865339a3121e4ec8f15c227ae9b6972b4c09b23599b3d5496816fda72d404a8b02da42332f28857ad1da782c0e5a82e67f249dc0c102ceb469d8b9c779c2d8639bd983b66ba08c66e9dfb3f41e4e94da5b9460ee1556a9fe90282bb653ec3d8c3a45318af2db9ea505a578a2b268dd695add6167c7c9873c0c176d1d8578d19c2c0f6f461f018d871883f128c61ddd2fceeaa52d3761709fd2a808f86b922d8f8d53e74e175a00a5ec483d26565071002eec928929d964986dae4d372a7aef8aded3f5be34e05f46dede4277d1e3fa0220c5736c52eb457ba5dda65dd9a4d5f421bb30c1a8f5a92170824eb0e81fa889915c69fed6f65aaa73633341e4e61eef215e5dc368f4afc43f6af9d2bb371be73e4b631a388798f23e1693be0875f12a41876c02bbadbb72c64f3fd68104d382a40c501799da5ba94d42a28c11cf872b1a24216f71eea2ddf4a0608773a92c5b11d0f59a07c0fab48ebe1da70cfb75e9c0fd421604b9a11a20c271b39ae644cd9a044e9e9d2fc6dfc52e270d5453330549e0b5756b42873d799a013df1f72abf25934b9fea2a480642844799e56b7228dd413250abb4af9afa5af713fd7f97b354abba8b6a4fc171571f84ae085782f07939c76589e76ab0906d554b7f13ac4dac2a2bfdd99032ee2cf9a8b5a5e22c43e7b82c81cd138ecb7c4dc6f378ca448529de708de8ddead5da3b2a8774ddd04c10dbb37408d62b8aea6cea21b5583909e13485c95c2d8e107566e7c7ee60b2c3d204b879ec7d5204b517db3b4d7f2fe293f547685932850b3c50000000000000000000000000000000000000000000000000000000000050c12151b242a2e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 68, - "comment": "expand_a requires 280 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "a7d7afe9fd91470612d6855fdf0776ab66c0157e00f45344ae5b4071effb517c20e417987ab3692ed9ed90c89b76fef1944391a6f1661cc44e882f82fd6e7a1cc828e93e0c9d7af99798422b3eabb4d221032c61790c29cf219c9509b9a03e637ae4c9111c88416b0c74acba9718c0824ef09887e00f32a596d4221d996344da98933cfe2fc858e3605b3d0346f9c9e03ce2892be2abda3e3057e6ba784ef28ed17e482a78e44b0064ebb03c1c1d0b94370e1d4bca2004afde50f5a8e76cedc1ed228666fef0d8226499a104f3176785e7484cfa13f61fbba0e24138b7ff38f851615591fdbfb80a5eea112ce977bbe90c747a654f589790397e5795fe49111a0f615486093a0913600df83c18c774a6eadbf9d582bbb468c4044e7891cc9510d790c53de923e3e78d1ed8c4a175f55b0b8db7c30077c0a76cfe206414170fadce56996b758882ee017303026fe7b20b64a159f39c6d7a43df35a10c13d8de74d236ea48e6ed08d53e96bcce6003a47c787b3b87940038ef5ab45d271c91586fc2c85c861874b7ce4f4a78d75555e34afa15a7ffcd252fe680f90dd595838b6df1c4e782d5533697efc898ca65638729a228da5d1d0b5c5658db4ad37918e006e60902407927539b2f9698218bd73e6e919743937da3bf23c6cae013064c50a71e9308ed3d1b6d595cb01b48445dc2183dab8d803f56fd88dd0eb4095c347e7c176807ad88e5de070f594b5ddca726a61fc95ae903a6a3416edfbeeef9416e6e59228b9ddb3d7b81ea5e402e4106182c8440b185ab402d2f585998edc0271b7750267dfc720b339aed5196f502e79456450b586f98f8ebfb7383ab68cec191d8dc53470cefcb6889c4062a0ab6f095c32366d56ff8d414f9b6d56d01f617638e44999bccb19378b295a78e68ad554e7cdf49ccd9fb9f582c46ae311f8de213db52074c9ad47dac1467506568d2ad2c50bdcae27a04ef2df25479e31ea3880e96588b3efb3a60aec2acbcec0fd2fde673e5f7c6a71ac958d3767152d8e7e2c206c97e059ec180d401a525314cbd2fdd902072f80a219817277b2788c21bb30ec340b7fb52c85dd5479284a2565e600ecee81df819e849265a738a156583732fc47d84e4fab298707df53776d6af160761b1563d9da8bff9a5bace5418f3e171b244c95a4a079c405613346ae035fccd8b7a9614c13b51314fa31ad47be50f666b18c636f6be3b4cb45a6286a002b7f73b5348cfb046b87599b03fc440e3afc138246348669552dc2af75174a1a00a06f8ed5df8a710b2c5ed2e5b97a75b8569b8cc76dffa6f16587f45006c3a4b0cc97c0afe88e31cbc67dde34f76a3a116d359187f39691ea49502f15fd302b43c9456f2075194fbed22120cc86f616b6d0a430464bbd0508a1b7014a2059f8be6679507c995629627f88154b401131d190bd603c84f487f01dad21240e8e3aa95c05998b771f9e7c4a719a1daa4b91e0a301904c2b0c94e7c6805e6f28b0c8adfe8d47e7f2978d1eb59fba567195b81e8191ccba6de77f19a16a3aa30d67955fc94b2b0a266da4b625a389f592f8b951bcfe5db743b1e81fb94373fb072d808e6f0e5893655d96933bb540ebeff179aa9fa98f36cb4c6a78e170dc859b753fdf9a51f50fa0b25fcaf25e1b31aeca1f3c4c024fdae36fa70d8cf3b8399c17f866bf2c33f0db659c9cb464a323904fc6e00cfd1a2cbf847bfa428d00c13d8ed229f56ff016ddd229b2de2727aa048b972359940ce72f88f4326b3570e4bb621fd5327b59abe425f3c7f547f283b7865e127e5cab181667141e810f6438da61583e9f702098f08235a6a80f1d9350e6ad4239cda1901637f60d1a8454d85399d324e3cf538be98649aa2572045d8c13fc1452b5ad60dd3b0ec35bd153aae1b56c48bee037d7027518136d06b4914b473f0de7e680b73692c652fb7db3a38159d9f1159e8df08e8352e8336e823a2dce3ec5cfac60ef625f7dceecd78cc21b6895c7c9dc858315fa0146aab6fb27ce8fd18eeee354dab50bf4b70e0a2eb9b11fc83701fcfaca9e5cb11ae3a76f05de2f9b2209d55062c75b06ddebb32b9972aeb240c98d31bbd31bfc0a86ed5c3f693e7c355604260b32712a6ec0db6d021d29f842d11da7feb1927d5f0eda6f7aea8e4f3781a437a28e9748610fefb3abaa22a6fcf2003552b0fdc320cb2cf62ae8fb64ad51ed175a9d216a0b044eb5c32dca5e9f4f98ab4e0b95b2f6af4028f2e2f1ebaa7efc010044413da811876d9b8356db1e6735e7d463a0335f6afa04ca6de1a7903f27b823cc271e6372da745bfedcf0b5bb0e18adfd9d4233d0fcd05ab8d79be0a7eb11f1ce2a7e052251cfad1ca90b5e4374ccf1a129ebaebf01cdd8d4ce61aa9f3c0796e9bedb5502d0e099c7ca15470765edb69795f0d73cfcac91df6f134e5d11e7d2e3b5c8ae8387a1994b21402d93d65ad72bafaac8932a9a3d2efc87dc68468ddc1b3c0c1f5013e10479a162c442af0374383d27126aab8b78808fc7ab84e6881fa83fc55ea78aaefa9ecd526d47e59cca876d7e7865575d3100a871bd9c3d17a22ef6bb94bf72b9cdb11f6c9c66a7849df8ac2519abde05bb728df9a94220c0dd10fd1bc7cd4a4f65a55ef47d7b9d63f9224216c82edfb171a76a06ef29ea233e6692101b7e0d648b107d2fd616a564543b8d42e74c5a2d05dc1dbbb8a1aa04fd5acca120ac80cade80ceea66a998e4efcde47a2d440d31348afe85eae79ec9cc7818be885f2fab618ada1d2f1fcce920e7ff318580586b4f775fe8648629377551ebda731d493b54b16bb19461bc484b23a673c152c0a9894e71d534b072a3721fe73bf69562539fe5e0ec82c62c13dad89d9666efd6df4c40e7083b5d507827bdca7dcf218bc854f2f66060826645446c6279408351c3bcd87bfa12e9ba3dd1b7f36f97bf2b0c3517fac191e40ae4edb5fad23b390596bcf8baf6280bb8d6a6a12a5b25127768a5b0c6d5294b41b2b8e19ce6826761332dbb634243ca7edcbbed12668157445e0ad5ddb8daed13d37c5e0f0298d39c1d484bc0bd8e2d2abda428c28bee13381b5d6938d512ba72de3cdce6d9b14d71f7e214ea49ecbe14b7ac81342d38d81647f284a1d363f44a5114ed53ce4fb57556509e6bf52f7f5ad57536803df6ab6e3192f3d5cd855ea68dab4fee624b570827e0c5009870f114d7aab9984e15944ffe95ceddb693e8cb267a9ab46cef54bac2f8f36db7a4a4c3aca9d67cad76b44eec0dc72ce535a8b0449ebce056024101c787732a41d23fc0d611bb8967ee3187a85ffae3c134237bc5a1ad2d8f8a3158610fdae45d0831cb28758eb4d28e2c71031342b44580110041346e697ef0329afd7cad7fbd7712c44b13694cdaccc59676137fc2d33517f13263696333850c72281c8a8877bafc82879c3a3ce307a4ae70bbfa6aec20d6ddf8c33a7e242d9e69256321803280be75a0196f00bc3cecce1c9a8ec07acc47cd23f356f37606f2356f499067a2ebff92c9d68c4f377bb69997953df1f244baa8a39f63ea389d307a04be4fdf7aed763dfc0c611665a4176f4a7f5c577795e500e0528ad304680dd866e3b887e2bb13f089df36a75416597b2b6de3e3f22e36ed44f5474a5e74f28a255a4ec6914a9226147a1bf67d901e8b11cd129740da02bc3319d02a4cdcc5ed8a7fbb2f156d7e067abd1e0df6a7c563429444b0a08762a964159c878f762fc460198242b119c995cb4d7cda51d9d262636c2894ca38ff95ef6fe48d543898d2ffc31e0dd87c00933bcff60232dd02c2b886d603fa587cd7dd8195a3d119bdedf2203c9dc298e1d50a0dfa4bcd10ad1aba9b047a653cc05ef4dc289d3612e59cc4e12a8d639825f4d02737ee63f1ef73902c49658c668ef38cd233012d7793ee215ea370bad665cc322908ac1a9205f7fec356436f0a6c0db616239b7b765123445682cf1595eafd3f9fe3022aeac0ce2e6ab691b89ca88dbb2f5cc599a933972eb5f76e0157e834604447d3bf79cc773930f2e6899d211b5ec72d045e557a82a3d0e5ba23ac77899979d2dba338f5d9dc049628f433396956260e53417f37b8ebde992246fe45d95e1284b0b1a2e927499a6f180171086f3549e12a2dfae7a54f4331e4e4f38eea863173a565f8dc4de9551da854c2f48397291230598bb1c82ac56fa01a0f5ec16e603c12fa45a998380c08d2f3778236339f2970a5cc78baf8fbc784fa1f6c88af0bfdf42627b4671b9b1024d06743048f5f3db053ec770be4c7924c87f948153138c726d6ed40d174c22af74a852cb28caa6ca74b67e5403d34c21821f70102e73cd65643e08036158c805ccab703a528dfcdd1bc58593fc5dd382b91491aa860d8ca204010cb3446fcc97b5dc1058109aa5e8b685658969ebebb521580e95b45fc733f257f80ee29acbeae96a1c82016fd5dca8ba3e37eb4ed6dd95c254d12199bf3104dd801fc9d34b8e6d9dbbc63d7fcf7e5851bbf666cf303e1a53e5711e5c5804ea92004f3591fbe9bf612478896ab042036315e447b00b5df1ebc5151c4f4d619b12e6769f79fb31f1cf6ae63550230b2cc4b6d975134faf9aa41c5da0a5913a78cd6f765d5a6bb5e3422ea98bd5d2c255b4a27d8aaafecbbe2d42801047679f4fed4d94b71ea8b44644a1abb434155eeca0e2a845e673162b205e6bf1b5f32f78dd0f1163a30f3f6c44588f339a11b62eead81f84aee14815d54979bb29fac6d95f3a329805b1cc9807f694ec9ce6c9be7bb85248ee7b87c0a5f9c186e4517fe48d59fe4da31d2a2691a21d056754390a04e6036adcc20b0e6ecce962ef86831236e96c0880564bcff60c0848f0fe351756f705beee4971907b77ed08a875494d6e9d230b8ef81820d698c361e6e0d242dce7a79c48b316cf0ba4a3970d1dd9a9a5c4ec3545e7781091ef5f78e143e3a0a4aa82b572d8acded5b6b18eaa07cb843ca7614a9aaaed2fc97e675d3f3436ce7c29b5905e20b7635ad6c1005018ad8edffcdb7c78a71ede3ba9f5a6b63f17881530395afc6518774b2b21cccdc91b096cc294e323fc2a02a3255c96079bca232ce2cf39b46c73b8a2f3c988a264e4b783c2ca30780a86be394c0b4a467be4aedad4c2c5f77fd8fca6b40500c597cdbcb20714dfae8897b788d6c7377ebac29da41b4f602cab6169a80f6ded9c57ab422a17f6115437f7732377378543408957e0a08cb5e0332e5d7f24f5a6e1ff5f2ba37596c851ffd47a28900497985ea6e06bdd6a62f621d7307d79a9e0caf9c5b576427c1b0a7dc5ba2a919c6d8deeeedbc6785fc4239ff24c82d3f8467738888c9c0f1bde66ccc1a42fdbb55001cb1eaa024d7e1e8a8a8b9d2485a2854c036d4ac100aa631ac4913d2a4682366562929b36b9eb3b8e67261149171b43daab34bb4b6cf17e5444c22a157d2d556457fc82bad151b3e63d0fa4a7395898b054f3188383145502023ce889fe1a3e4b2393c992ca2686ac3de193de0e62f22ffa2db0748d1706e5a9215c9f51405ce30c265b898dc516a2cc4e216a803ff9fdabcd97b21b26dcc4c438804627cadc7146b222f520f0537d5d405085502e6acc498cf67e2f3fdb525480ced94b8d3bf63b677fae897a555ba99314f4fb02831ef82c6c9eaab8ed392a7e48db1f8d1cfc4a243d3865339a3121e4ec8f15c227ae9b6972b4c09b23599b3d5496816fda72d404a8b02da42332f28857ad1da782c0e5a82e67f249dc0c102ceb469d8b9c779c2d8639bd983b66ba08c66e9dfb3f41e4e94da5b9460ee1556a9fe90282bb653ec3d8c3a45318af2db9ea505a578a2b268dd695add6167c7c9873c0c176d1d8578d19c2c0f6f461f018d871883f128c61ddd2fceeaa52d3761709fd2a808f86b922d8f8d53e74e175a00a5ec483d26565071002eec928929d964986dae4d372a7aef8aded3f5be34e05f46dede4277d1e3fa0220c5736c52eb457ba5dda65dd9a4d5f421bb30c1a8f5a92170824eb0e81fa889915c69fed6f65aaa73633341e4e61eef215e5dc368f4afc43f6af9d2bb371be73e4b631a388798f23e1693be0875f12a41876c02bbadbb72c64f3fd68104d382a40c501799da5ba94d42a28c11cf872b1a24216f71eea2ddf4a0608773a92c5b11d0f59a07c0fab48ebe1da70cfb75e9c0fd421604b9a11a20c271b39ae644cd9a044e9e9d2fc6dfc52e270d5453330549e0b5756b42873d799a013df1f72abf25934b9fea2a480642844799e56b7228dd413250abb4af9afa5af713fd7f97b354abba8b6a4fc171571f84ae085782f07939c76589e76ab0906d554b7f13ac4dac2a2bfdd99032ee2cf9a8b5a5e22c43e7b82c81cd138ecb7c4dc6f378ca448529de708de8ddead5da3b2a8774ddd04c10dbb37408d62b8aea6cea21b5583909e13485c95c2d8e107566e7c7ee60b2c3d204b879ec7d5204b517db3b4d7f2fe293f547685932850b3c50000000000000000000000000000000000000000000000000000000000050c12151b242a2e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 69, - "comment": "rej_bounded_poly (sample_uniform_eta) requires 2 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "a7d7afe9fd91470612d6855fdf0776ab66c0157e00f45344ae5b4071effb517c20e417987ab3692ed9ed90c89b76fef1944391a6f1661cc44e882f82fd6e7a1cc828e93e0c9d7af99798422b3eabb4d221032c61790c29cf219c9509b9a03e637ae4c9111c88416b0c74acba9718c0824ef09887e00f32a596d4221d996344da98933cfe2fc858e3605b3d0346f9c9e03ce2892be2abda3e3057e6ba784ef28ed17e482a78e44b0064ebb03c1c1d0b94370e1d4bca2004afde50f5a8e76cedc1ed228666fef0d8226499a104f3176785e7484cfa13f61fbba0e24138b7ff38f851615591fdbfb80a5eea112ce977bbe90c747a654f589790397e5795fe49111a0f615486093a0913600df83c18c774a6eadbf9d582bbb468c4044e7891cc9510d790c53de923e3e78d1ed8c4a175f55b0b8db7c30077c0a76cfe206414170fadce56996b758882ee017303026fe7b20b64a159f39c6d7a43df35a10c13d8de74d236ea48e6ed08d53e96bcce6003a47c787b3b87940038ef5ab45d271c91586fc2c85c861874b7ce4f4a78d75555e34afa15a7ffcd252fe680f90dd595838b6df1c4e782d5533697efc898ca65638729a228da5d1d0b5c5658db4ad37918e006e60902407927539b2f9698218bd73e6e919743937da3bf23c6cae013064c50a71e9308ed3d1b6d595cb01b48445dc2183dab8d803f56fd88dd0eb4095c347e7c176807ad88e5de070f594b5ddca726a61fc95ae903a6a3416edfbeeef9416e6e59228b9ddb3d7b81ea5e402e4106182c8440b185ab402d2f585998edc0271b7750267dfc720b339aed5196f502e79456450b586f98f8ebfb7383ab68cec191d8dc53470cefcb6889c4062a0ab6f095c32366d56ff8d414f9b6d56d01f617638e44999bccb19378b295a78e68ad554e7cdf49ccd9fb9f582c46ae311f8de213db52074c9ad47dac1467506568d2ad2c50bdcae27a04ef2df25479e31ea3880e96588b3efb3a60aec2acbcec0fd2fde673e5f7c6a71ac958d3767152d8e7e2c206c97e059ec180d401a525314cbd2fdd902072f80a219817277b2788c21bb30ec340b7fb52c85dd5479284a2565e600ecee81df819e849265a738a156583732fc47d84e4fab298707df53776d6af160761b1563d9da8bff9a5bace5418f3e171b244c95a4a079c405613346ae035fccd8b7a9614c13b51314fa31ad47be50f666b18c636f6be3b4cb45a6286a002b7f73b5348cfb046b87599b03fc440e3afc138246348669552dc2af75174a1a00a06f8ed5df8a710b2c5ed2e5b97a75b8569b8cc76dffa6f16587f45006c3a4b0cc97c0afe88e31cbc67dde34f76a3a116d359187f39691ea49502f15fd302b43c9456f2075194fbed22120cc86f616b6d0a430464bbd0508a1b7014a2059f8be6679507c995629627f88154b401131d190bd603c84f487f01dad21240e8e3aa95c05998b771f9e7c4a719a1daa4b91e0a301904c2b0c94e7c6805e6f28b0c8adfe8d47e7f2978d1eb59fba567195b81e8191ccba6de77f19a16a3aa30d67955fc94b2b0a266da4b625a389f592f8b951bcfe5db743b1e81fb94373fb072d808e6f0e5893655d96933bb540ebeff179aa9fa98f36cb4c6a78e170dc859b753fdf9a51f50fa0b25fcaf25e1b31aeca1f3c4c024fdae36fa70d8cf3b8399c17f866bf2c33f0db659c9cb464a323904fc6e00cfd1a2cbf847bfa428d00c13d8ed229f56ff016ddd229b2de2727aa048b972359940ce72f88f4326b3570e4bb621fd5327b59abe425f3c7f547f283b7865e127e5cab181667141e810f6438da61583e9f702098f08235a6a80f1d9350e6ad4239cda1901637f60d1a8454d85399d324e3cf538be98649aa2572045d8c13fc1452b5ad60dd3b0ec35bd153aae1b56c48bee037d7027518136d06b4914b473f0de7e680b73692c652fb7db3a38159d9f1159e8df08e8352e8336e823a2dce3ec5cfac60ef625f7dceecd78cc21b6895c7c9dc858315fa0146aab6fb27ce8fd18eeee354dab50bf4b70e0a2eb9b11fc83701fcfaca9e5cb11ae3a76f05de2f9b2209d55062c75b06ddebb32b9972aeb240c98d31bbd31bfc0a86ed5c3f693e7c355604260b32712a6ec0db6d021d29f842d11da7feb1927d5f0eda6f7aea8e4f3781a437a28e9748610fefb3abaa22a6fcf2003552b0fdc320cb2cf62ae8fb64ad51ed175a9d216a0b044eb5c32dca5e9f4f98ab4e0b95b2f6af4028f2e2f1ebaa7efc010044413da811876d9b8356db1e6735e7d463a0335f6afa04ca6de1a7903f27b823cc271e6372da745bfedcf0b5bb0e18adfd9d4233d0fcd05ab8d79be0a7eb11f1ce2a7e052251cfad1ca90b5e4374ccf1a129ebaebf01cdd8d4ce61aa9f3c0796e9bedb5502d0e099c7ca15470765edb69795f0d73cfcac91df6f134e5d11e7d2e3b5c8ae8387a1994b21402d93d65ad72bafaac8932a9a3d2efc87dc68468ddc1b3c0c1f5013e10479a162c442af0374383d27126aab8b78808fc7ab84e6881fa83fc55ea78aaefa9ecd526d47e59cca876d7e7865575d3100a871bd9c3d17a22ef6bb94bf72b9cdb11f6c9c66a7849df8ac2519abde05bb728df9a94220c0dd10fd1bc7cd4a4f65a55ef47d7b9d63f9224216c82edfb171a76a06ef29ea233e6692101b7e0d648b107d2fd616a564543b8d42e74c5a2d05dc1dbbb8a1aa04fd5acca120ac80cade80ceea66a998e4efcde47a2d440d31348afe85eae79ec9cc7818be885f2fab618ada1d2f1fcce920e7ff318580586b4f775fe8648629377551ebda731d493b54b16bb19461bc484b23a673c152c0a9894e71d534b072a3721fe73bf69562539fe5e0ec82c62c13dad89d9666efd6df4c40e7083b5d507827bdca7dcf218bc854f2f66060826645446c6279408351c3bcd87bfa12e9ba3dd1b7f36f97bf2b0c3517fac191e40ae4edb5fad23b390596bcf8baf6280bb8d6a6a12a5b25127768a5b0c6d5294b41b2b8e19ce6826761332dbb634243ca7edcbbed12668157445e0ad5ddb8daed13d37c5e0f0298d39c1d484bc0bd8e2d2abda428c28bee13381b5d6938d512ba72de3cdce6d9b14d71f7e214ea49ecbe14b7ac81342d38d81647f284a1d363f44a5114ed53ce4fb57556509e6bf52f7f5ad57536803df6ab6e3192f3d5cd855ea68dab4fee624b570827e0c5009870f114d7aab9984e15944ffe95ceddb693e8cb267a9ab46cef54bac2f8f36db7a4a4c3aca9d67cad76b44eec0dc72ce535a8b0449ebce056024101c787732a41d23fc0d611bb8967ee3187a85ffae3c134237bc5a1ad2d8f8a3158610fdae45d0831cb28758eb4d28e2c71031342b44580110041346e697ef0329afd7cad7fbd7712c44b13694cdaccc59676137fc2d33517f13263696333850c72281c8a8877bafc82879c3a3ce307a4ae70bbfa6aec20d6ddf8c33a7e242d9e69256321803280be75a0196f00bc3cecce1c9a8ec07acc47cd23f356f37606f2356f499067a2ebff92c9d68c4f377bb69997953df1f244baa8a39f63ea389d307a04be4fdf7aed763dfc0c611665a4176f4a7f5c577795e500e0528ad304680dd866e3b887e2bb13f089df36a75416597b2b6de3e3f22e36ed44f5474a5e74f28a255a4ec6914a9226147a1bf67d901e8b11cd129740da02bc3319d02a4cdcc5ed8a7fbb2f156d7e067abd1e0df6a7c563429444b0a08762a964159c878f762fc460198242b119c995cb4d7cda51d9d262636c2894ca38ff95ef6fe48d543898d2ffc31e0dd87c00933bcff60232dd02c2b886d603fa587cd7dd8195a3d119bdedf2203c9dc298e1d50a0dfa4bcd10ad1aba9b047a653cc05ef4dc289d3612e59cc4e12a8d639825f4d02737ee63f1ef73902c49658c668ef38cd233012d7793ee215ea370bad665cc322908ac1a9205f7fec356436f0a6c0db616239b7b765123445682cf1595eafd3f9fe3022aeac0ce2e6ab691b89ca88dbb2f5cc599a933972eb5f76e0157e834604447d3bf79cc773930f2e6899d211b5ec72d045e557a82a3d0e5ba23ac77899979d2dba338f5d9dc049628f433396956260e53417f37b8ebde992246fe45d95e1284b0b1a2e927499a6f180171086f3549e12a2dfae7a54f4331e4e4f38eea863173a565f8dc4de9551da854c2f48397291230598bb1c82ac56fa01a0f5ec16e603c12fa45a998380c08d2f3778236339f2970a5cc78baf8fbc784fa1f6c88af0bfdf42627b4671b9b1024d06743048f5f3db053ec770be4c7924c87f948153138c726d6ed40d174c22af74a852cb28caa6ca74b67e5403d34c21821f70102e73cd65643e08036158c805ccab703a528dfcdd1bc58593fc5dd382b91491aa860d8ca204010cb3446fcc97b5dc1058109aa5e8b685658969ebebb521580e95b45fc733f257f80ee29acbeae96a1c82016fd5dca8ba3e37eb4ed6dd95c254d12199bf3104dd801fc9d34b8e6d9dbbc63d7fcf7e5851bbf666cf303e1a53e5711e5c5804ea92004f3591fbe9bf612478896ab042036315e447b00b5df1ebc5151c4f4d619b12e6769f79fb31f1cf6ae63550230b2cc4b6d975134faf9aa41c5da0a5913a78cd6f765d5a6bb5e3422ea98bd5d2c255b4a27d8aaafecbbe2d42801047679f4fed4d94b71ea8b44644a1abb434155eeca0e2a845e673162b205e6bf1b5f32f78dd0f1163a30f3f6c44588f339a11b62eead81f84aee14815d54979bb29fac6d95f3a329805b1cc9807f694ec9ce6c9be7bb85248ee7b87c0a5f9c186e4517fe48d59fe4da31d2a2691a21d056754390a04e6036adcc20b0e6ecce962ef86831236e96c0880564bcff60c0848f0fe351756f705beee4971907b77ed08a875494d6e9d230b8ef81820d698c361e6e0d242dce7a79c48b316cf0ba4a3970d1dd9a9a5c4ec3545e7781091ef5f78e143e3a0a4aa82b572d8acded5b6b18eaa07cb843ca7614a9aaaed2fc97e675d3f3436ce7c29b5905e20b7635ad6c1005018ad8edffcdb7c78a71ede3ba9f5a6b63f17881530395afc6518774b2b21cccdc91b096cc294e323fc2a02a3255c96079bca232ce2cf39b46c73b8a2f3c988a264e4b783c2ca30780a86be394c0b4a467be4aedad4c2c5f77fd8fca6b40500c597cdbcb20714dfae8897b788d6c7377ebac29da41b4f602cab6169a80f6ded9c57ab422a17f6115437f7732377378543408957e0a08cb5e0332e5d7f24f5a6e1ff5f2ba37596c851ffd47a28900497985ea6e06bdd6a62f621d7307d79a9e0caf9c5b576427c1b0a7dc5ba2a919c6d8deeeedbc6785fc4239ff24c82d3f8467738888c9c0f1bde66ccc1a42fdbb55001cb1eaa024d7e1e8a8a8b9d2485a2854c036d4ac100aa631ac4913d2a4682366562929b36b9eb3b8e67261149171b43daab34bb4b6cf17e5444c22a157d2d556457fc82bad151b3e63d0fa4a7395898b054f3188383145502023ce889fe1a3e4b2393c992ca2686ac3de193de0e62f22ffa2db0748d1706e5a9215c9f51405ce30c265b898dc516a2cc4e216a803ff9fdabcd97b21b26dcc4c438804627cadc7146b222f520f0537d5d405085502e6acc498cf67e2f3fdb525480ced94b8d3bf63b677fae897a555ba99314f4fb02831ef82c6c9eaab8ed392a7e48db1f8d1cfc4a243d3865339a3121e4ec8f15c227ae9b6972b4c09b23599b3d5496816fda72d404a8b02da42332f28857ad1da782c0e5a82e67f249dc0c102ceb469d8b9c779c2d8639bd983b66ba08c66e9dfb3f41e4e94da5b9460ee1556a9fe90282bb653ec3d8c3a45318af2db9ea505a578a2b268dd695add6167c7c9873c0c176d1d8578d19c2c0f6f461f018d871883f128c61ddd2fceeaa52d3761709fd2a808f86b922d8f8d53e74e175a00a5ec483d26565071002eec928929d964986dae4d372a7aef8aded3f5be34e05f46dede4277d1e3fa0220c5736c52eb457ba5dda65dd9a4d5f421bb30c1a8f5a92170824eb0e81fa889915c69fed6f65aaa73633341e4e61eef215e5dc368f4afc43f6af9d2bb371be73e4b631a388798f23e1693be0875f12a41876c02bbadbb72c64f3fd68104d382a40c501799da5ba94d42a28c11cf872b1a24216f71eea2ddf4a0608773a92c5b11d0f59a07c0fab48ebe1da70cfb75e9c0fd421604b9a11a20c271b39ae644cd9a044e9e9d2fc6dfc52e270d5453330549e0b5756b42873d799a013df1f72abf25934b9fea2a480642844799e56b7228dd413250abb4af9afa5af713fd7f97b354abba8b6a4fc171571f84ae085782f07939c76589e76ab0906d554b7f13ac4dac2a2bfdd99032ee2cf9a8b5a5e22c43e7b82c81cd138ecb7c4dc6f378ca448529de708de8ddead5da3b2a8774ddd04c10dbb37408d62b8aea6cea21b5583909e13485c95c2d8e107566e7c7ee60b2c3d204b879ec7d5204b517db3b4d7f2fe293f547685932850b3c50000000000000000000000000000000000000000000000000000000000050c12151b242a2e", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - }, - { - "tcId": 70, - "comment": "power_2_round returns a remainder of 4096", - "msg": "48656c6c6f20776f726c64", - "sig": "a7d7afe9fd91470612d6855fdf0776ab66c0157e00f45344ae5b4071effb517c20e417987ab3692ed9ed90c89b76fef1944391a6f1661cc44e882f82fd6e7a1cc828e93e0c9d7af99798422b3eabb4d221032c61790c29cf219c9509b9a03e637ae4c9111c88416b0c74acba9718c0824ef09887e00f32a596d4221d996344da98933cfe2fc858e3605b3d0346f9c9e03ce2892be2abda3e3057e6ba784ef28ed17e482a78e44b0064ebb03c1c1d0b94370e1d4bca2004afde50f5a8e76cedc1ed228666fef0d8226499a104f3176785e7484cfa13f61fbba0e24138b7ff38f851615591fdbfb80a5eea112ce977bbe90c747a654f589790397e5795fe49111a0f615486093a0913600df83c18c774a6eadbf9d582bbb468c4044e7891cc9510d790c53de923e3e78d1ed8c4a175f55b0b8db7c30077c0a76cfe206414170fadce56996b758882ee017303026fe7b20b64a159f39c6d7a43df35a10c13d8de74d236ea48e6ed08d53e96bcce6003a47c787b3b87940038ef5ab45d271c91586fc2c85c861874b7ce4f4a78d75555e34afa15a7ffcd252fe680f90dd595838b6df1c4e782d5533697efc898ca65638729a228da5d1d0b5c5658db4ad37918e006e60902407927539b2f9698218bd73e6e919743937da3bf23c6cae013064c50a71e9308ed3d1b6d595cb01b48445dc2183dab8d803f56fd88dd0eb4095c347e7c176807ad88e5de070f594b5ddca726a61fc95ae903a6a3416edfbeeef9416e6e59228b9ddb3d7b81ea5e402e4106182c8440b185ab402d2f585998edc0271b7750267dfc720b339aed5196f502e79456450b586f98f8ebfb7383ab68cec191d8dc53470cefcb6889c4062a0ab6f095c32366d56ff8d414f9b6d56d01f617638e44999bccb19378b295a78e68ad554e7cdf49ccd9fb9f582c46ae311f8de213db52074c9ad47dac1467506568d2ad2c50bdcae27a04ef2df25479e31ea3880e96588b3efb3a60aec2acbcec0fd2fde673e5f7c6a71ac958d3767152d8e7e2c206c97e059ec180d401a525314cbd2fdd902072f80a219817277b2788c21bb30ec340b7fb52c85dd5479284a2565e600ecee81df819e849265a738a156583732fc47d84e4fab298707df53776d6af160761b1563d9da8bff9a5bace5418f3e171b244c95a4a079c405613346ae035fccd8b7a9614c13b51314fa31ad47be50f666b18c636f6be3b4cb45a6286a002b7f73b5348cfb046b87599b03fc440e3afc138246348669552dc2af75174a1a00a06f8ed5df8a710b2c5ed2e5b97a75b8569b8cc76dffa6f16587f45006c3a4b0cc97c0afe88e31cbc67dde34f76a3a116d359187f39691ea49502f15fd302b43c9456f2075194fbed22120cc86f616b6d0a430464bbd0508a1b7014a2059f8be6679507c995629627f88154b401131d190bd603c84f487f01dad21240e8e3aa95c05998b771f9e7c4a719a1daa4b91e0a301904c2b0c94e7c6805e6f28b0c8adfe8d47e7f2978d1eb59fba567195b81e8191ccba6de77f19a16a3aa30d67955fc94b2b0a266da4b625a389f592f8b951bcfe5db743b1e81fb94373fb072d808e6f0e5893655d96933bb540ebeff179aa9fa98f36cb4c6a78e170dc859b753fdf9a51f50fa0b25fcaf25e1b31aeca1f3c4c024fdae36fa70d8cf3b8399c17f866bf2c33f0db659c9cb464a323904fc6e00cfd1a2cbf847bfa428d00c13d8ed229f56ff016ddd229b2de2727aa048b972359940ce72f88f4326b3570e4bb621fd5327b59abe425f3c7f547f283b7865e127e5cab181667141e810f6438da61583e9f702098f08235a6a80f1d9350e6ad4239cda1901637f60d1a8454d85399d324e3cf538be98649aa2572045d8c13fc1452b5ad60dd3b0ec35bd153aae1b56c48bee037d7027518136d06b4914b473f0de7e680b73692c652fb7db3a38159d9f1159e8df08e8352e8336e823a2dce3ec5cfac60ef625f7dceecd78cc21b6895c7c9dc858315fa0146aab6fb27ce8fd18eeee354dab50bf4b70e0a2eb9b11fc83701fcfaca9e5cb11ae3a76f05de2f9b2209d55062c75b06ddebb32b9972aeb240c98d31bbd31bfc0a86ed5c3f693e7c355604260b32712a6ec0db6d021d29f842d11da7feb1927d5f0eda6f7aea8e4f3781a437a28e9748610fefb3abaa22a6fcf2003552b0fdc320cb2cf62ae8fb64ad51ed175a9d216a0b044eb5c32dca5e9f4f98ab4e0b95b2f6af4028f2e2f1ebaa7efc010044413da811876d9b8356db1e6735e7d463a0335f6afa04ca6de1a7903f27b823cc271e6372da745bfedcf0b5bb0e18adfd9d4233d0fcd05ab8d79be0a7eb11f1ce2a7e052251cfad1ca90b5e4374ccf1a129ebaebf01cdd8d4ce61aa9f3c0796e9bedb5502d0e099c7ca15470765edb69795f0d73cfcac91df6f134e5d11e7d2e3b5c8ae8387a1994b21402d93d65ad72bafaac8932a9a3d2efc87dc68468ddc1b3c0c1f5013e10479a162c442af0374383d27126aab8b78808fc7ab84e6881fa83fc55ea78aaefa9ecd526d47e59cca876d7e7865575d3100a871bd9c3d17a22ef6bb94bf72b9cdb11f6c9c66a7849df8ac2519abde05bb728df9a94220c0dd10fd1bc7cd4a4f65a55ef47d7b9d63f9224216c82edfb171a76a06ef29ea233e6692101b7e0d648b107d2fd616a564543b8d42e74c5a2d05dc1dbbb8a1aa04fd5acca120ac80cade80ceea66a998e4efcde47a2d440d31348afe85eae79ec9cc7818be885f2fab618ada1d2f1fcce920e7ff318580586b4f775fe8648629377551ebda731d493b54b16bb19461bc484b23a673c152c0a9894e71d534b072a3721fe73bf69562539fe5e0ec82c62c13dad89d9666efd6df4c40e7083b5d507827bdca7dcf218bc854f2f66060826645446c6279408351c3bcd87bfa12e9ba3dd1b7f36f97bf2b0c3517fac191e40ae4edb5fad23b390596bcf8baf6280bb8d6a6a12a5b25127768a5b0c6d5294b41b2b8e19ce6826761332dbb634243ca7edcbbed12668157445e0ad5ddb8daed13d37c5e0f0298d39c1d484bc0bd8e2d2abda428c28bee13381b5d6938d512ba72de3cdce6d9b14d71f7e214ea49ecbe14b7ac81342d38d81647f284a1d363f44a5114ed53ce4fb57556509e6bf52f7f5ad57536803df6ab6e3192f3d5cd855ea68dab4fee624b570827e0c5009870f114d7aab9984e15944ffe95ceddb693e8cb267a9ab46cef54bac2f8f36db7a4a4c3aca9d67cad76b44eec0dc72ce535a8b0449ebce056024101c787732a41d23fc0d611bb8967ee3187a85ffae3c134237bc5a1ad2d8f8a3158610fdae45d0831cb28758eb4d28e2c71031342b44580110041346e697ef0329afd7cad7fbd7712c44b13694cdaccc59676137fc2d33517f13263696333850c72281c8a8877bafc82879c3a3ce307a4ae70bbfa6aec20d6ddf8c33a7e242d9e69256321803280be75a0196f00bc3cecce1c9a8ec07acc47cd23f356f37606f2356f499067a2ebff92c9d68c4f377bb69997953df1f244baa8a39f63ea389d307a04be4fdf7aed763dfc0c611665a4176f4a7f5c577795e500e0528ad304680dd866e3b887e2bb13f089df36a75416597b2b6de3e3f22e36ed44f5474a5e74f28a255a4ec6914a9226147a1bf67d901e8b11cd129740da02bc3319d02a4cdcc5ed8a7fbb2f156d7e067abd1e0df6a7c563429444b0a08762a964159c878f762fc460198242b119c995cb4d7cda51d9d262636c2894ca38ff95ef6fe48d543898d2ffc31e0dd87c00933bcff60232dd02c2b886d603fa587cd7dd8195a3d119bdedf2203c9dc298e1d50a0dfa4bcd10ad1aba9b047a653cc05ef4dc289d3612e59cc4e12a8d639825f4d02737ee63f1ef73902c49658c668ef38cd233012d7793ee215ea370bad665cc322908ac1a9205f7fec356436f0a6c0db616239b7b765123445682cf1595eafd3f9fe3022aeac0ce2e6ab691b89ca88dbb2f5cc599a933972eb5f76e0157e834604447d3bf79cc773930f2e6899d211b5ec72d045e557a82a3d0e5ba23ac77899979d2dba338f5d9dc049628f433396956260e53417f37b8ebde992246fe45d95e1284b0b1a2e927499a6f180171086f3549e12a2dfae7a54f4331e4e4f38eea863173a565f8dc4de9551da854c2f48397291230598bb1c82ac56fa01a0f5ec16e603c12fa45a998380c08d2f3778236339f2970a5cc78baf8fbc784fa1f6c88af0bfdf42627b4671b9b1024d06743048f5f3db053ec770be4c7924c87f948153138c726d6ed40d174c22af74a852cb28caa6ca74b67e5403d34c21821f70102e73cd65643e08036158c805ccab703a528dfcdd1bc58593fc5dd382b91491aa860d8ca204010cb3446fcc97b5dc1058109aa5e8b685658969ebebb521580e95b45fc733f257f80ee29acbeae96a1c82016fd5dca8ba3e37eb4ed6dd95c254d12199bf3104dd801fc9d34b8e6d9dbbc63d7fcf7e5851bbf666cf303e1a53e5711e5c5804ea92004f3591fbe9bf612478896ab042036315e447b00b5df1ebc5151c4f4d619b12e6769f79fb31f1cf6ae63550230b2cc4b6d975134faf9aa41c5da0a5913a78cd6f765d5a6bb5e3422ea98bd5d2c255b4a27d8aaafecbbe2d42801047679f4fed4d94b71ea8b44644a1abb434155eeca0e2a845e673162b205e6bf1b5f32f78dd0f1163a30f3f6c44588f339a11b62eead81f84aee14815d54979bb29fac6d95f3a329805b1cc9807f694ec9ce6c9be7bb85248ee7b87c0a5f9c186e4517fe48d59fe4da31d2a2691a21d056754390a04e6036adcc20b0e6ecce962ef86831236e96c0880564bcff60c0848f0fe351756f705beee4971907b77ed08a875494d6e9d230b8ef81820d698c361e6e0d242dce7a79c48b316cf0ba4a3970d1dd9a9a5c4ec3545e7781091ef5f78e143e3a0a4aa82b572d8acded5b6b18eaa07cb843ca7614a9aaaed2fc97e675d3f3436ce7c29b5905e20b7635ad6c1005018ad8edffcdb7c78a71ede3ba9f5a6b63f17881530395afc6518774b2b21cccdc91b096cc294e323fc2a02a3255c96079bca232ce2cf39b46c73b8a2f3c988a264e4b783c2ca30780a86be394c0b4a467be4aedad4c2c5f77fd8fca6b40500c597cdbcb20714dfae8897b788d6c7377ebac29da41b4f602cab6169a80f6ded9c57ab422a17f6115437f7732377378543408957e0a08cb5e0332e5d7f24f5a6e1ff5f2ba37596c851ffd47a28900497985ea6e06bdd6a62f621d7307d79a9e0caf9c5b576427c1b0a7dc5ba2a919c6d8deeeedbc6785fc4239ff24c82d3f8467738888c9c0f1bde66ccc1a42fdbb55001cb1eaa024d7e1e8a8a8b9d2485a2854c036d4ac100aa631ac4913d2a4682366562929b36b9eb3b8e67261149171b43daab34bb4b6cf17e5444c22a157d2d556457fc82bad151b3e63d0fa4a7395898b054f3188383145502023ce889fe1a3e4b2393c992ca2686ac3de193de0e62f22ffa2db0748d1706e5a9215c9f51405ce30c265b898dc516a2cc4e216a803ff9fdabcd97b21b26dcc4c438804627cadc7146b222f520f0537d5d405085502e6acc498cf67e2f3fdb525480ced94b8d3bf63b677fae897a555ba99314f4fb02831ef82c6c9eaab8ed392a7e48db1f8d1cfc4a243d3865339a3121e4ec8f15c227ae9b6972b4c09b23599b3d5496816fda72d404a8b02da42332f28857ad1da782c0e5a82e67f249dc0c102ceb469d8b9c779c2d8639bd983b66ba08c66e9dfb3f41e4e94da5b9460ee1556a9fe90282bb653ec3d8c3a45318af2db9ea505a578a2b268dd695add6167c7c9873c0c176d1d8578d19c2c0f6f461f018d871883f128c61ddd2fceeaa52d3761709fd2a808f86b922d8f8d53e74e175a00a5ec483d26565071002eec928929d964986dae4d372a7aef8aded3f5be34e05f46dede4277d1e3fa0220c5736c52eb457ba5dda65dd9a4d5f421bb30c1a8f5a92170824eb0e81fa889915c69fed6f65aaa73633341e4e61eef215e5dc368f4afc43f6af9d2bb371be73e4b631a388798f23e1693be0875f12a41876c02bbadbb72c64f3fd68104d382a40c501799da5ba94d42a28c11cf872b1a24216f71eea2ddf4a0608773a92c5b11d0f59a07c0fab48ebe1da70cfb75e9c0fd421604b9a11a20c271b39ae644cd9a044e9e9d2fc6dfc52e270d5453330549e0b5756b42873d799a013df1f72abf25934b9fea2a480642844799e56b7228dd413250abb4af9afa5af713fd7f97b354abba8b6a4fc171571f84ae085782f07939c76589e76ab0906d554b7f13ac4dac2a2bfdd99032ee2cf9a8b5a5e22c43e7b82c81cd138ecb7c4dc6f378ca448529de708de8ddead5da3b2a8774ddd04c10dbb37408d62b8aea6cea21b5583909e13485c95c2d8e107566e7c7ee60b2c3d204b879ec7d5204b517db3b4d7f2fe293f547685932850b3c50000000000000000000000000000000000000000000000000000000000050c12151b242a2e", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "8588d98656a8f17295805d1b38b207dfbcc02a5192031b1e8960e51dd6bbd9b1bbd51ed5bb48adb19b8491701b9026c336c2a8582d6b08a35de3aafac9783e8e49002338f0a00d356d24477b8711dc6a577a5720cf7fd1d6ae2c7b6b265a4b6525411a17fb611baae4a9730a8a5abb336275c424e117d6922816352402e1261a869c5b5f40079a8f1dc484837a620724e7b0079869eb6314eb5217737ae800e6f3a6814f8c026a57a4892d22b684a5d359e7ebc10641807bf8b741e24877fb89e4500876feedc0c71cc639c3552b1ba06a728ef3f003b24dd0101cbe8f29da5ec8d5509bccd6c2aba9daa53ac7e08883de715539bf7cc9d1c851469faa2cbc459d3a521f0aa46468bab11d2902483c1323e8832848de70adb3c0b37c70063f8208df91568365c50b97da9a4244e16f0a2347470396420d86b8149e32324e03a6603915bef7a1dc44223bacf40bc4c904f89c6985c21660edc3cd69281610b48ce57282677e42df8e45f9d0b672a0aa8b3b72019d36a960a0443f4504186972b51731c8113a5b06cd5ede73e8167bffaaec4b8324fdda805cdd36d4cafb46450666f3a51794ee2e07c0dfe6a49060ebf1ab9bed0fd88ca2e48bc2559b4c41ba456d1bfc35d21feded9fcb815a155d2bfc2bdbc86711c83af22d3f3a4eef139d884e038bb87b2f456f13d4803210d58c73ae4930b25a9b3692ffb328156a3c13b0f1cf2aef1cc1ea537a0861c18404af3e1fd6fa3d435bb5770019500ab9a6cd7bae4090dd2c128968f9b9f8bdcf6d2d3e9aaea608f289c5256c62733b34338d4adf0da3884f1a89427de4a84ef3337d07cdd67fcfc75b3aa917eff209494d6eb1e20962eb0cd78711f591cc4fdb6cfbe09b19b2447337d23a3418d48008ec09c89263e7f3071c2b31e1f930ae5a22afb8f384cc978b360fb8d40821e91a9257a6759820966de14055847322defc22adbb3658100b9ddbb769b3959a82974ef0f773179a915708b27ce1c77b29884cacb8bacc64698bf8807e1f0b547cfcbfbed552f82b1a4726028ae8bc62eb216d135b444b10a85579423eca650d6af51865ea8d201ebf1af8e0daf728d4e9e8ed3acaa2232b1aae7d8f0fa61ac5fe090aab85345cc0e7d8250ae0369039b490a9269369cc04a71dad427dd4218c37e7e25290bf69d91a1096d108e987ad173983e79726e2837f37cedcea9e4435bcab9ee9065868328835950c981045d35957bf800b2cceea1b62ea2bfca0421942eb5bfff92a520fc589a813caff8bd8614465bcb76949a8c169b040110f792bce3ec51ad3f1e928989044c1a8e19da9f6d0176a2299eb801e3733e7414ff41fb87b153e94f1e440c9b7aae73c9be84fd4c0555d1513ba715b8e8f71c8c554ed5ee43398180057994dc8fbf96eed5937c46d592d8b99b5026fb3cf9627b87dee0713ab235590df4147fca0069daaac0c3bb1eacf80a20526eb1d20a686ccbcfc9995505593b3125677082b9f6436d46a5ac1407612c673a2f215a774eb877f87b625b7d5213de29976d130e94051f2b384db0c19930af0633189d1afe540ebadd1ac25d7f7d3b18c28b2d39dd24e1a92a4a9a44d1cd05a3ffd3de2b8f896376d58e31c502ca9635d0eabbd3f13df636dce0442b7289776b3b715de865f8583a5918431cd525b068997cf6892239ee6e7b85703f700dc845d64e09e247509bab4e6d5f3c450d205a860090e5cce5aa0418cd496538748329505fb7344d43c7c2b74caa8421013e65148000678db1ac10cc0d57ceef594013cbf9c320ce400a2d3eecc3a485f9f698f26de5ba0c0634021611ddd903e5e852f5eda123fb9fd1af241e78a35df610423634545877ea48e9173046a1c145e498ce044b5d582c032e5c8e29358f2211aa61aba2f6dbc56bae0731d636b52efd0116d8c2c1273f0db9e8a6f65f741c618b6899cdec9ccb6459e57ef9184107cffced74a7b527b5aff9d3f79aad58e0b623bc072d300f87180a8299e42d35fb900572f27036582c1cac5b5a5c95e92e3212ec80cf2ce008f724954add2f738c120e6cbb0c0a68f1e0cff41723a735c3a2e3d509558e77534c08ead4230b20eaa0bbcd423eac7b4f8962c5c70a60558e0a2fda9db6eba4e02ecf21f4cb3b5954698872a83b6ded84a78ceec5c18177d2c71fc8e74ab9635012250d62eab8a7ebc3b19a6cae092dd1e1e72d3ba84006f776859e2daf62c1255eda7e02956664e9e3aebfab6a4a3b6a8cf0ac64d4dad686e6dd690df0dce8ba28b303a882a5c39672c1422d10624647b0b702e504d076576c2d47a6f02aed6941310618b6162bcc497da020c750db539e0c6d086e3ae09250d4294f9b772d02fa0e55d32e35a66806a75ce0dff9d38a4d17318f6fba0d30525106828031111e53b3ba790ba3fcd355c834371932ccf311112feb5cc718b56fa757797b2cb6f04600aeaa2df5e892eec16735c9766d1ba13cd2fccec23fe20a87535b057d8e44e5de0eaf953532057dc2087ca124ec424bdce48e6b720673cc51131b2c04d951835e66258fe853f826477556fc285aece334d65a8191df4aaeef17b23359a5c5e5aa1daf41eec8abb5e03681c952695433c9c002dbe552edba2ffe36ae3322dcbdbcab44261c88fa6accb4d1f98795203566134d9b2b7a1063f6f44ca205656d31f2a815f047000ce50989032a3dc5a518d4d796be4250e540a13009f4dde1c753c92ae802b59d3c0c99e5880c68b28dcf49bd6dc72dc4cb44523265e05f12290e20e79036677117552123f449f26498d439d5ca94aa40bd89fa9933b84922709bf38ed0f290f8b12939049148711d81306de859ecee53db24b31cfa26f677d7c848226a53fe9ab7a6380808a32abd252cb1fceffaf40efb5e4d875c8359310f5c93a847e1c679da807a82ab676db55520ac9098376237bdb840a32818e7d99e50db8f33e2fe8a5e6229e5679f246c21a0f03d87f7051ae5e9daa8cc4320421751f906a910669849e5674bbefeb72a4e1b2aced14cfa9f6bbc336ae019bff6567a4d51af0da32bff7f7a8416c803cc027709699519f78e969ed60b06c3bcc0cc4f9fdbc941a214a195ddde34fcbc10e1a33f104f689867687d70f17ce59a3f951b405cf7ed001533a85d9297c5a969798e20463ed46c2f067f5fe0b4f86d907516fdc3c43a8ab9eb31072ae3b678aed7388f8ad2998fc13a5e676c53dfff8a66e47779e5ae34769e8ace88f2d4cff23296ce5ef385da456857e7ea5b7fad1e84b16754bb576704e25d2b348f3f66377fab0972ec8b00eeb3cc708bbb50c57de13b7aa01526108731e27b2c54210fc8c9e592155f51d429dbd63b8aa4e3cbf9a244c777f6ceb5469cc031e2994befeeca067ccb9df827e59e6466ac4d73ea3e6bffbd0a229f66007d40c8836300baa677f9b1f5f5cbfde8a9fac8682a00e263a86910897e0b5bf3a3f7a5aee58dda4d5312f51db1286db5347260de1c9bfe1510e5e40e2f2db75f7a46b565e58bf8d00e99a982ac90d0e92a87b84baec2e643d38d82ff704060b3254fcdf148fb6894cdba71416d880e82b18ff8371ed3c5141cfba6178cc5c9cdff24b73064274804131e8580a49c35b8e539f0fc014e8915c948620da8753d6f171f6e8fbd07827b1a601e36061343a2a", - "tests": [ - { - "tcId": 71, - "comment": "rej_ntt_poly (sample_uniform) requires 783 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "824d1cb7514b18a56d5748687760d2b9526f1d0a18d270cfd60ed0ff9aaa803eb07eafc190ddc0832edde35a932986b5c1764d70815a9c9f7fe5969d46a1c071f93f1eafa64f41caca4e7ad8f1e0edc6e70ae9e7f231b8c6fbf513b834d12bd8b73c77ad73332016113ed5f47c4fcf2cbaabb1300899d8537211fe24973f220ca81935f5fe4d2b8573351884e8422d772b0f1fa26a9ac2dc5b4a7b2f48076de4ac57d720ed7a93dafed68604934f7837f2cbec5de640f3db0a546d60a7e19bb79155018382cefa88d5b0e2d9b687580e08537528b2d3f115ae60ded747af81eca1ca6844d050d43a988ee357593dfe395e39be2d8ba623fe3a7694c7fb3951be47f7d73398386552e417c9a256d1c319fd20901798a33324e90dec62c76cb21e3a7d2356ea94e6e861c451ee1571b1f9d5b9e051dd33f83089ad14807acf9dfe5f35d4d9c7a122f6f9f3515492eb982f2510cbd1e07a8cfa7941cef0b4155239a6b35c74fe4a2049bfb86a0d1cdcd340ce070ceea71268610c94b17945598ac2689fa1ca2915b87984594ddbd7bcfe77aad9e9f83b29762c20bf13276eb5d08837a0483346273e06b4bb6ca25886313da63296eeb2be0174524335c53c127f32665f34e5a9f92f1f9aab6ed7ec88e9ce9de97e92c59581660fa3c8e7f49facc9edf6b5d74a1913700150e119f0c2d42e05ed7dbc47c129f760451083748b433e164cbf4d24be64a7e5bee9b8ffbd898996eb7e7c527bc54f0c333c560ddd28eec2d07fe9c195c1b3219b31594ea6b3583fcf4bd8d611a5057b7e30611992ce7b260f716addc984f1f11aa75c79d269120a625162a085cc15e65c2fb1a27c5bbc501b5ef639c18d672ee8faa30ed685a91e0a2bcedc1baf16bc650dbba5a0c3b61ffa75fa324e785f2621ab9a031ace88440ead9e1f9fcc2eefe61ad7a7f13eb6f328a48500aeb5b1bab4efe42e3f454f7466b5f7d522b53290b71613dda88d33f0e0b9323fa7d517e28f764f127a18f7670a20a19a1242b3d1f2f09e87e4c29ca10eac5bba68da7b7e7f1037f870d98cfb5f695f41e072063ca48cf014120aba2874ad45238e81db4c05e9cace7f5682c7365b7f0848df395ce6a8e389f7cb557364faf091e4c8583f02b2e27ad1e97ecf5f900da0fadd8d07b3028cb6d41e5c1336149044b0616227e62211e96776ae6ae44b76cdf65d8a3591582abce907d47cf77ac17647a1a31c4a8b895634eda9efcc4d102e580cf02db33adb4da0ae06f5c5051e36e870165caf6361f65166e9fd240846568f4f71763f3429a2a2d7db2595e258e4366ffa5b7258b1959207f501e882e8fabab6851ffaae49276146d0ac88ea325af90ddde57403a0c0ed225dbe5998191735370d314ef70d6a8550ff8a95a16a5a00a3d625814464650486534c2253499c39adc420e18afcbbdb46cb7321bfe1aae3424825ef8667e60b71ce9753a07d316153aaf080a1c7456b58940e3b33ef722add1272e0ad34cbe1f1fd9ac5082453112edaf080a4dc549a89feb86972693f6f3acadab761ed292a2e58932a694cae8a6c50056ab287094e89f097930acdbd7128856ab3c843481745b045427a22a82e0acb500cc604f9f2bc51d58f37608dd94637223619631c265dbcf1576abf5dae24502591b241876b4292779305b1d039b39419839522374598aca889d33477f52a74bdf4f122153a07e652b714c8dcf8b0e1d6c2efc3715fdcf794122a9609735b29dc86f21661754f8e377b61bf7ecf7211534b7eb084cee29216cb0730a9730d8daa9008efbb9e4535c638ef1baf6fecf14d4083105fa969be606345139298869894076d03658a64e830be581da3e41e0426e34fb8ec007f16fa8dc17565058e5973096d672632f16dad1df5b0780c55aa33ba50984211049d24cbc73a6faddeb123eb8456d56b9f8b57dea16f2416f0c04a54ff867e577e1f91dc5d9bdd4370819613cccdaa76441b5dddf6affbc685a087c41adb415642539a6fb56e715898c846197da31056a95a121a68936cf9d832dec4daea2f2af020faf28e7ed8cb2c7a835b5ee464924a246f82658daaf3368a19a9fc82ddd55939bd635f1ca0a90f5275623c2a284ba2ff80c583fe22d2b8f13a3786f4ba831bc53c4052f02e59f22c58728d1e7596e7fdae6686a861cc60dbc8319a796a8824ff21dafa001f3a52c2d4b4b91b6d67d8cc43b5ad5b3dd4a4adfa7429cdfe08e8ec9a1dd277eaeed010afb5b06440f9bbdbc66a105e23550bd85d48eff83c804384e04d97557e75d7b8ad7028a00139478482a9ddecb07f21c3be63c6545bc37f6affadd0929b5c16dc84d86c512955fe54fe163fd4adfcb77b387c96a6be34d58c5169dbf9e81cc69559a4ce7dfb054c3544c240823904146c589746365208687c5b5232989995e62f86d0be5f7cbc0d2124d9180c41d11d61a3ba3f1d9ac21a4ce4b9555fc95868adeb72ca09ceedd636bdd1fc57b9d99e04de68a0182d844b435b0c4173b41f712897497b508e448f48420ea74e77886670f66f7b8c5ed73070fec37fb6d975e2d65f74fa3223a6cc3e182cd5cc69284ca7004a0a9c9a6ea25b824d81841b450033e27a539443255926ecd530c8b7645d64727ad709857f0dadf270a987715b1f5dc12eb2294a1682737c94d3eb3f5cdf5beb7d913ffa4212a6d0d37b7bd190267be8e512881f34ace3b17a9b235482f91e5ad0be7c553a3da884b001deaaa16a427f819315b31403cc744ca23e629f6c6ca1c12e1046468519dfa89806488c78f12416efee7162960f2a094ca2fc08302e64785f606f729e8828e9f5d0e26e3d23fc884f5f1e2ffb82580bbb055a6d37763f3cab61472d4fc88ed6cc0ac893119a095adb77ff88975184eee2e96bc6607c13e755041f783d38837f244684d5cfdb4192aadb72ca69893234c99f71a20bf1e7704bec43ac13a31f26dad6112212047123de6fa1f88b67ad057432099ee9fdc5ef6de38d00b432c3ae148b49480d32c89328d74b1f0091ec7f3443860db0ec3652c3ea85eab79e61b051014a0820f1a6690254455c2182295f6add3676b6a8a9bb8ca4a9b0290feb9f583199b6cb11a005992120c3df1e7487abeda49052787e0e0a44bc1d1365f1f20504505bda4fab2f7a150395d2beb11221420c17b878d4a1a4bcac80ada40d007e30663856c5b94b67179a2365d68c6d3de7e8a3b190ea0aee2b3ab20fc7211a17098b6a56bf59d68ac83dbca75cffe38c53d68b83c6ebfb451b02094a0435cad7f09ea339cc2221c3490638f513655461030b2e7d726e26ac6e463284614e6af5c4facf431f4e9e154b69d9a8c09fde2f958d91f55f2b0b2894b736621d399f2d792cdfbc16a55de8cda76e60b3983e83179da4bf0873d0aa38f6dd6d87af2efc7eed5242a842f9438644703f7d863ebf681e68105b59a5644bf9da92d42e5426a1865a46acefb7c62e1bb8d9e2a50e7746b4993da65045a35ae83941eec217387e824d4d01e6c9ef58667a0453902ab6ddc01e27c936092c896cd4165cb18ed3331b86f136dd558e7aeeab5eac0a6314d9c3b231a3b7c12a5c2a92623760d8e55f41d56ddf5883bcf48c7fcc112aed62d6ae325b84ed943965fa62c7f5906883b324a2af74793cd9de5b3c5db7c85d642a1f44f06e73956846361713178183a8d86446f20fef418afc5558189cbf79fd4d31802d3bd551d5d2d4453db9de00a18486217d1e2e7b6d55da62d5687f4a05f9fed2666fcf65962982ccd9482f6cbd6c28cfcb405d1b71ac14c20af75e009a3170fd6a6acbed65d2dc052c380b4119d76ca0f1005b5acdd7cd4b57d450bdf117f6ecd891fbcec94922c357cca9da31e52e0a1e697dacbeb5af8787e444b15ca22f6c35c738923352f917174f0c8d221efaa67881b1ddc987ad35a0a19b695e3cad552f23111e4e20de5650591bbaf47cbe7c5377826a239094db7c053fa59de0ec9a4ba9df9c01bba53069a4344dfe1ef8f3c69a3b50cef238976468e7d3235a7a5f5ce55422ad75fad7783379a10ec017e3b6eb88374c72414df2e20c3b02eb86db32b59af9ed8b986175e5706db428cd717e4ad2e00205ac678f684ed8f8bc005aab5aab9838670a6d0c4d9b86c856cafc88a8cbc90e3263228f9629fb55a73b9cf68db84940c543895d5d5c3f82a72de407b035fdd54ad38a7f9fc59f25a27dd615dd94100f22429f88c84e4d2b0d02857685428d8b9056eee45fe0e4ce5bd99ce44d278a81d871d9be130670716050ce8c19c1d780c5d8841d8ebb7994e3fe95faa9e41ff0c52efeeb07e1d502df1c785d819529d1869acc9c14fe9d7b772601fdf74f668f3671f5bdefb2624168e69a35c3025698eff33e47edac30896b1fa1f9ba9bbb44dd8608040973ab88e7bbc89d3618b3ad9780ddc93db16176dc819fc246825076110ed8e70c2d6608f03accb53aade4a0f566fa6d98b7987c72fca8e9498702c0add15eadc4b22edef393d63afc398c65a2cc59c40033486afcbb1e0d046021d7835102bab7acf30ad4c9ca0567473e06ebb121e726063191a43384292cbe83990bef78be8e76e4f3d7ccab3ca1a5df5065af212d27422401eef5ac48ac19775bd9ef5658057f33de7c0fbadcb29814fa0a5a7e70b3b618f506d003a8c747fdf5173cc049f5aa11ad07238086047a381fec834b8796f1e6a8bec08a42ab99697bec3a81cac1d6517e85e25b9376e21b76c80499583d9dd40d8ff7f027d9e85ff32f8c5df2c2580f089eee714e5a480714fae2333df8aaa3963d397371d0d660b41c34f5847dd5bb04cbd4c7eb2998b9359f7deb343dfaf8c39ebb0a2759b40dc299e6b751055cb0acaf6d82aa78f312358a8382ef4c188ae2e5a03f580d65b02ed621fd2d29413204ae8f09ce4bbcfb66930a24a411c499d19db0daaa2dba05d5b664d71fa3b84613a568e4c0f33867caf03bea41fadfc967c68344477cd698ca4266ef52c5432d6160c4b54ff7fc48fb480a514e6b1a768d95d41baa5eda7126cb30df72617468443b536deb889742af1e2b54e9e40282f162cb1ea22336b4644a4fe6bc30465ce19947292be53de619d90ae3a8f84b0d3c521f35f5103fe831b19f21e394f90167ac2854954a88c4533665d92e8353ddea094b2853ef0d87d18f7bea773221bf0ad169c1b00b2a57d0bc1e4d7fe0b72f4b34d6e66c2ff02292b45b1357be6378c2b7e5ed79e9c8d5ae5e626a07f55c3586fc864c846824c4dfe875ab372898506136dd1373b01de258038690c7eecf4aa7e30451b8e727ae9eecb21f5517281df0d279920c65ed5f337285715c5644614ef61b6e9fedbf915c4cdb816f39aafa394a85451115462e2644234348d3c77e124bf9d8f2261d329db5bba5fa801c9318538d3bda2349a8f12323626260590186286ffe60bc28ffabe493f4690b2e23353fb632d5f89bcbc9d40c6c08798abd8b8494ccf3ed3f79a5926aa6e12a3a98db6964e6d6fc78204e5c409332082d79fabd1ef299da5b2f0478d2f9d4f75ab7063b71dbb9264e05ac4d25d902eaaa73e3809a62f0070445fcf02318c7512d80c413818f96a4ca4daeafcdc607453e13c1292b99847f7a72ae2bbf0e0198c348cb0b6a956236b03d307fbbdca0fecc1a7ece3172a89f99f6ba430dceb0c1072522506f89180dfca1b905267ff30e29efb740191e173f8c6f37ce68e4d221f0496f537e7ee24d1d22fd248d5b2ea1db5b2142199556f815f98e20e9a9898d838db2165dfc6f41da561de60c21adc0de22e54f13e362b2204fca7d4e683d7351ad49d854dc731f8b31a6bfcf66d0dc5c1bd84f48a3103357216c9322d48db897351bcb92c3bc51b80681ca57591affc4dffec4bdcc052987a493b3b03d509e3eeedc374051a42b3f8de363e3e85def860fa6792084a06779e0c7de781a2a68fa698a748a3a626c2dfd7aa430833d340ecd37e4f931d1144c8194c08b905397996dbeb75d6b13fa46d1f70f96c2e80b41dafec454be48a0d75a41393cd1ec7317ccbf9869f8aace999863aeea0dcc0e9bf8c386baf8bdfec81caba7d89bca80f56bf7ece1e1dc642bbf3964b0d09b9bc72b58e4aa6b8b6202aa38f2d346208045f3b2ca13aed23f96dcc834c7c702c91eeb3aa83d76d39234e8848da3588a6fca135b2bc2dc88e7db7567cdb2137b79cc35ceebb2b745f4e9432876faa2365371734cc545a13c1e16889a6a1ef8bc660dce212332eedc8f3a752f1e0476d558aa8f3c0ba0ae7c9f4944334a4cc22eca0a0bf96efb127e84f863e44818aae7dfc0db0789f12fb580b65d1865aa09ad615bc7418bb50ca5d21fd6c4cd399f4c41d0fa04ddc7b2f6b87f31eb73dca62b4042f9baed135cedb0fdfe5bc503dbe52be75817e3f130a530d0f38aca6608947c243967bb025396b20536a0db0e286f79ca2e385f7287adb3c2c7d3f3ff060d1f30416d78c1c66e9ab1bac41a2022252d52ce0000000000000000000000000000000000000000000000000004080c111d262b32", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "25f4d547d98e744400f34dcd9f981c093bdbf073efda689f75c9cb0b7ddebf3a923d2fe5b73851190e53e51070b5148bcc410160306c3d55c1b3abc44a0b6a395cda04dd37eca2d0b85a5fca41eefa0cdf3fb0e23269c86d9c672e302e06e2cc434546b1f0840320793c2e49e209773c5e33e1f48a15a7afdf7d22fc402be2b079d2949b97e2b5cde7d54e8ebc43a607e179fbf425642d19b1142405732cab458df2577e697f845b270ae358e2b52191b615ceec4fbdc603fe4fd3ebe2ae3ba453df7aaac4725bcbddb6305dffd96928165e1cab3c1b35a22af68daf8f608ce76846afbe56e7714836e51390d2e1a1d73937dfa929af63ed618c54efaf15a8a0e7ed67edbaa6e91233bfe8685324cdc5938860d89761a77c85303c2187e0c43501c8c52634068d0f9b9f8e7100e3854385fc2d9686ff103e1e08871eec0bb9922d3591f1053e3bf6801213b48845fd50fad5ccf3d0666e2ef670e2e55427a15d47a933081a6733724523d71569c8880465fe9e033d85656640dd794d927333c2f413bad0c879a9647f416f5ddd5995c31d4243d78ebc7bfff5e3ef40eef15489a46fb8f7a9a219d46b5febb2da05df69575baf090a8a5e3ea1b1c1a0be21cb2af48cb1bff6a3192c3029cc5c6414ad951df2303bc72ce5c79db6bfc786c3d61c3bcbb99db3704c6fa8ba4028c7d98621a3363bb6c2a1606a6c7568b153b6ac1568625a85ed6febc2cf1ee70cbc8acc86c4a7ff16ad92cbb8f2ed015bf290c8ddb9517ba40d871ec50e2b6757874ffbbb0f2b90558a336082c2a6a835108d753488ab2d9847889bc498a5f9e0d6d9de4551737d4b6bef415b4a93d12acc3bd892f9d07b486a321101e534dd10da16af361a037f5a03d002db82a0d2d83828eea09788224acb547330506c6492de585e1a6a1ec09e6cdd7cafe20cb12e145280d8d26143e0fbcc087d59dd454079ad0663975dd7e313b9852534bfebfa03df2090c2517574a561ecd83aa6ab0cc3401f16431659d863f6f8872f0b6661e72b717ea2c0e0539735591e7da8962fc21a0290982cc4b68fa1a145fba69bd49d9b65095abefad11c037f61cb067a42818b7609d7c827ecbdf48bb991743081f6f31c6b6f8a85b3e78e073eba11bfbbc7d99d034696869940cab7185b40b3409c8b32becf76079b8daf4d2b6385124f1671eeff6046f4ba441c23168efd425c0b2797442d53cc7aef25f6b7b49ce7f9010fc6e9db8ab569b4b540eb104873b50e977a53d278813706c54bb769ea5777e61cd101f30dc81f9dd7a6f34bf1832209959363e54e870dd2416520bf502b3e411d66075aa746a264c1f82b3ab6d54bb5540000e6357cf155c43859c98c477a87a825979b128c44866019571fd555763f83f44d309cdcb03ed913257f6fec48fe9fd6acf195dd14d8a957d5d70def35a5408aa888072ab555e77c3ab10f8c513d4a2d45db8c218e227be7602c9c8b083db5de23055d4edc93fd91b5657b664303c8306c227696ad7f2ddc280a1e5bf176bc951083a851394a375717f9cbf58675890e76584aa2ed8ef76bfc1315842d476d881defc23c5794402091268c8e3e6d0c10428370555b3f90ced0139cf97eea1bbc1b1bb422f3d192f519b17cc64ca6fcae84f1bd5abf6a9a06c46af994d0333d5104e7140b256ba45cac064283c4bdb4563cea069fbd352ea8ed955e94e8374379ddd54cc9f4df410a0c19e8d10a030c1b94004dbc196d56db099566d2c7ca21093d870b1111f4a313ddb21736f3c6a1e05b43da8e4b6ac90ecf3dd8c7d0dee7d309ab382c5bea92e059be92cb982573db8a3c6608a5c4e61b386b6b8ead0f0c283742eb8a7a1af41e544b04ed70f3faae1cf406749a66e685fd5836e632732070a3770888e73381a923d5b7dda4e3b8524f3edbd01310d35174f326d6f9c92b04974f20d0312a4eabaf146c143892168673aa4dd64290f7b23858c64b1561758e324cd25810e523f454268b2fc9374c3e6ef221ed554d7eba7d3a9eb7ef48578f0c35f2da48e8028581d74f7cd4b4eb2c8de328be2cfbe8bd12d7db37e513423e525710e13ac97226a592e3fdbf615c07e66ad298c0834f0bdcad6e1907d7548dc3f206de5bd64cd9d03d3bb2041f2d04d248e46aeec73181f99a182be2abdaddf402c58a0950074641602321caac2f6f1525366b473a4bde4d828fbc44f7db5ee1e1c067a36ad6493145da896fcb88e56c00eb0e4d2ad8731538fa255d9de15cfcd7a7baef6c8f3c8e11204d2868c2f057939ff66f44b1051f4a1fdd99bf9beae873805ae684723844b0d64b44561e75f57a59605e2270e9e3bca4a420256ae1da44c91a1d1ddf40faf8b44a73334c768ebc6521db91847f148542836c6815b7eb36008a6e91b0590287b6d2ff2adbd0fe6c7f65e73ddefa4ce51241e3c009930bfb5078a1b4d1b254e1ce6fba02e25f8c8e83e64fbf7485e6592c4b49f9b9c1d698d596ab1bc25054d122da1a1e7dbd1ad7703b766b4359946fc421c9504c9f3050778d5a5adb9c926c823762b710b9d977a24cb27fe94aaa61ddea22661b9769469f0ddcecb2490c818006a4101d90c51b48e814e526e5ec6753165fef270254ab7dcf62a715c5ff3559403a1b7d9affdae6d2aedb5fa5c4d4a452aa4d44905aae91543c69efc7b9de727b366cb3e219c3d464d8dd8542598d212ca38f9d0c9f4718dce48241dfd1a9228ed1b79798dd38777006cc6cd2f96662f45f89e03b8aef1dd71c938c612aefbb247eee03decb18039eee1d8c4012ec4bf50f92c95ff9801a5db8b293ff6ca65ef2b68b6ad483a0c4cb9e54fc51aa7627170477995d8cf55a88b886a23e28355f7ba06e00277dc6435d8de9982c8f2fad4c11725f0720fde528e7c1a025f4a74c539cbbeddcf5fab57aee327e3d1f4e08ec0e4feb16d700166484a16a43402319a2d7af2d1323a24cce5c7ddcea43d998972b35a90e87692c5f461d8d2d7129fffc82172d32b236ce09defe6e001d591df31df3cf25b29c9dc533121a545b826511ae0b8781af17bda9b35618957cb8c7c3f13a847df03ba14ba17d640a6b65583ac876a87e553f0aecd293ae6f05400f10cc7388f6e8744be7bbf4f3ba1b8f52fc24d08e8695e1a7f39b1620ec25af50685af27dd5213e669838c0a0f7527f4de8135695780833042dd65a7d0252e38c13da862368062f74fd04551b47dd9510b25fa904ab75c5d91536e5e60b34fc0d9a8ffc81824df0ba378a4bfb7bb0a13a72a51bee349fbdf6abb1fe88ccdca25607ca1b4725eaa795c573d74d1ac4d47b6d22f400f94b500e98c97bc268b34e0b492140416c2ea6c8068a489153b84854e63ab75580173f884c6854ba66062dc62af9cc72cce5371b4c1f116406943ef50468ba7b4681bbc3b01c441c1de15dc80920ba8684502a5638a1d03d5f85e4ac383086661c44876dca736bc7215219a4d7c023d594574e9ed13b011e58bc942d5b3538513eb5c8fd3bf34dc9e69f0a97f236656e2cc04b9de03900bc860c34866b6d4fbc0c0a5d784196d45062d56885c5c3805e01c152e1f9d0c7cde36f43a7d5b184b20c155518ea1a108280faeb3d59b7db0778d4370a14d9013ee377692d1a2d770683c970463779a6af762af2b643af435dbb0f", - "tests": [ - { - "tcId": 72, - "comment": "expand_a requires 43101 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "3bd8a330720ae098ce18a91f1c1148bd9bda16cc884103204ff052a5f1133d5c960a10476bbca4da560cdc0f480760ac22065bf261bce2537590ef44e0d6bdcbd92ede4c20fe81215c0d964b00ac8be59299d5d028b52837e7f00ad8f66159973ba89c721963d6aca0b291708bb828a56b0cfb117a23f1ebf98827b2303aebddf7aa79f4fd40a31e40355a25083536b74b7da1b237110daf8d605af058584a465c497b229f9b07dcd8afc136d949344e2d6239b7cdca2420931344d9df1d76d3666b4eedfdcae5261fa4f14f1364f8a40c3da4781c8e829d67800dcb70a1bac2d89eebb678c543090caf2e076de40b8121cac7dc081b664a77728bba0dd42f44f7bea10cb3711da2c420bf76a1b07ae82c6b24ceafe583fd992adf8d6e758b4047a9b221605593c55d4282f3055aab5f099bb47db4da5f5669627eda064b5fe24805b64e61e461e1b7be2c29e5f8ed77a6dc13c95b9561a905549bfb347b56ce5969110bff0c350e91036a4a3c9606c2854e36ceb0cd89d43dd3942194c43897e6c9a90fc73df067ff29245678b518125115ae94888c772a5a34a9587ea947fe38234bfad90dc4ce8d2e6d6e7722b666c10926a9dfb22cf5fbbfb5fe924ff8b171c5e4a3147f57d4c5e6ebacee9fbf9e6c451fd488b8d1e6ad7584990ce09e46da4878964968e003f9d20a75e07e893c2ec641a72db52462b81354e7870d272e629ff82f22a1027e71c5f951da08246b8dc9aea54ad9c6e6b40dd5f27ea1fde1cef3951259dde0ded49ef8173b5ed1791cd901ccf8e3ba548ea6d615ec8069705e06e7f317f91da016bed5588a64f2470830384bf6e15791b6be584840299459fbb1ceff7b20caace2eb6ca5dd181154c7d84e2366837989d203699138e111b5afd28224650b8d0c7e609c14c5c2b5bc6401016e55a89fe7548653304753e6c1e2e193d592942cf16011ba89b08e216474ad2f2698411fe8f79588701fb8d52fa0714d5f79a444a84fe4c0c504de0c79b27adc20bae190a0793418b2aa9646c54e59eb58020690835ac3f5e335e8a2d9bc0f9123fb6239ee992fae6859e3570a45ea0ffafa70dfab017d36e02dec51624cc7796c1efef1078fcf28e13e7efd2a440011a4cc2820f977a2f135b310f397bed322d9b600e007472e64f9e07a99876ff3db537d0d9b97b2b2a8ff061bee1ffda8c870755f0274b5bfb83c4263a4e84220875217ca3119b6c6262c59113558317f99a30b7524f359f0941646e61bce553058cd1395bf8df2dc16b66f51fd5e1c042440916b001c0b73e0d4ee1464a2ab73bd69c80f0d1f3e1c5bbd4a39494bf24f5158e0363acde4eaaa3424cc83f77da1213186701facbcdcd7ee8e3c731f49796cd01e96e54c01767edc77694aa6bbc9fdef67794f13332d488dbb0ab2167bc500413eb39924abad04c48f53d153384a6dfcb8af3b6ffe7e0a0c14c9f309aa706dc244eb42ec3fb925108e45eacc8f5415ab3ff57a3b3de225003ef13dbc21251c903965e69261856033d151b88fb697a3d7c3e199bdeca8937c32170591e0cc5c286a01e5c512eccbfe26714e348a971aca0dd2d669353d45b8e87568a30d03c12a12d83c67bc34d5a78d0dd0b879a57a96cd79e049d9fa7a70f09e12b338b99f3fdbf576321363a2683793c05a05a337fbeb3bdf634780c038dec2616104321bf06f597e43d1ef71fb32cbac554b53e6a7643d398ff9a61d1000cab3d2fc23f7a5a7f8239cd686c6f9832d29f6c480b7412c8b1ed37fa0b7017323b42fccca68d460270239f1591c01444dfa776f5872343e583a9b4158c5036d5103ed5abaaa38c6359ed9329c106ac23793449eee8f86a231ec6ee6f6aceb5747b6dfb8087049a1d095dc923148af4df3ed1640e95ac628495e8239cd36f673266a088401abe66165b5795ee2cfd88008560dba5616ac4d640d815537c7a15daa5f2b2dd21613ff68c9debdffaec713b8fa77e6686d20e70298f4418e939e2972da8acf3b129c8b7b00c359642dc2cbd0a3f1db5c08ebf6679ebc07adf98aeb877c68eb85bb5b817b53f844249b803c3ad3e89b6a4b4fa1a95d36c0e2b34db2f11c02882e3875bab66f0bd65f4ef201bd81b482af3fae4d174da68649be7a5e9e43532b916b5da09d2c6bc1872cbe4700f0ea416f1d6fcae680caf07c0b471e3de808c0c17ecf4a8c1e25351f57a5f5eea84b6434c76437190f8c9eeda124d3bd5c104753cbcf47411c5040f5d99626bf6f9ac8830b78dad8211766ef06ff26f81d74e8eb9816a15363f13db35e184d491fe36f93d112b8425aeb5f9dba074563d252a849a0b495a68f058f48aedbfc31f395e6962471fbcc074e132c06148da2a9541e23605ace30f0b68d46b658bff2d467304f2df3830b214ccd10c48c20d9c82370409c83a418d3c456927c87a752f43d8240f14899cf5ffb3cf55758cb279f91fbda0f97838b4e0a46f2b63348725710c8c2fed635ad9e54542f1508480e40e29db3059dbebd111ea688e9b104a938c519f48cfe34c964639f945abbb93b25b44b7c610c7f739993cc07ac7a80372e6136c422b3a61e9c16921ba93448629dbf11a428f1e5368981d5bfdba09943613a59557d56324fd1455695ade8fb9b45e99cda2fde8265db9a7a6760473f85eaff0681d0fe700be3d77f19ab743cf3bd3451e48b166c298c56e39f2b8dac4f3afcc2fb9a25409af657bb78f4c29cda57aa717c7544051b3486bcf0dac2469cf09329d27e03230281bd143e5bb99a88510c78af1339841059b1c24b91a855afc193f3332753b2333690b7893bb94dd9d450f062d44e7ded70b64bba3dbaaca4f9478ce2d5147bc9e19b23c0c09248340d5b95baa00f6d0e62d36d9a99e4f8f800729f5723b001977b8c5d6794cc663a811cbe0aa9b8638b8e8432fc2aa24373bd36fe2f09ecb8d9da7227a0c7113adaf606b4ed0561bc3f87ba928781f642cbe016ef499a1eb04a05e99c22c83e49741ecc9607c3a7f4a1a09e1a6a97bd2273df905d3e40759934ce4ce80177210dbec959104d626c58d6b9588c44c919b98d8c89f42380644ef05181e5663bda0ebb4f48f236784fe7aab78bafffb303819b93aafe06b93f1b5216eb2b80a484f6cdbda09f1f8493074be39f1cb0b5b44b67ba8baa820850dff4c5f7c23c2b4f28b40e21aa67a74bcec6e2963e6c78d58b4a420300ed06a3f1bf90945090a4dcc9d3c5f73608fe8036a74a3aa42b92e2fee50a80093ddcf7c0c2dd0952f8b6ff99b7a8c810e356dd61d9f42bbd2c127b20f4cf588d953d0c1ae616d9de285cbac73f877b583e88b9e4f3d796d1d6bde5810ef01025a419d07fafbbd17a0643b8025e92e56b96014e818fb7312127652f92346087e1c0734afe0d5bae257b9989b8498d8b359280f62a8fbdc402c29a5838a75eb46eba53fd8a8db37fc1ac1033b89e57652b319d70a230830065f56b85aec16632d12b6a40b3739ddba16545700c4625dc871b85d3e092a15925b394767af947291208eafc47bd9d59dbf234cdbe502db4030c6e6e980d46470564db718943fb5209041dd5c55de544f54807d60a2c3fb10e20af0c998fb0460b7da2ebc0cd8f660c9d801a1924b3551a5e9289dea7888f1af35a4bd4478e0aee320a165ee4065827108c6a30c4fbcd154991d1a44564fe8aa911516f02fda8d746b9469b782248eaa5d1bcef641683054c182606db1502c4455ee54ee96d02a4ef9fbe0c0235e7de64ec59d37a61ba9c158976ac94d36f1ca3a775ee2755c42e5c3fb191c8ca32325b53e20596483fc1b0f2bac57886f6c1cd25894676f911c4793718c5de83afef5062f98eaf0ea7d302bfdd060baf88fa1b36b6097e8dd0f77717d4ba08aa103091cec35259be1fb5ce62bb86bccbd2b57d0d4f11a03ff34dadc34d4448a2fb5292db2a9ebff02224987d873e39e34a2e87cb67cf768d4099e211e60cc8b55d419b15f22ed9ea2ed57da7e9a2f51b30cd2b7eedb3985756175f26dbf6e5edec90cd17555a722ef430d22f899522cc856ab9cc2f7780ba64d5bc8efdd6826d25d1da679d46a4e7c340075ae4d4bde2c0928d6268000b5c19a6eea92b3be895ba437cafd573be98f364adcb88f20106db881e03e884d33a950379b9acbc5cd3dd25f0027149f6060ffbd38a0f99f030e9dab149c25ed84369edd73a9befda24c741f796b6fbeb080c196112cfb152fd71f00e6364abb8b82ad4a46dc773a9708524fc512514eaf18568d1ccc23dce012ac5e7dd7bc5983e9f89b4ca49c21b25233fbc8ca483a2a166a3a6a95d94a139e43ced630a0ce365ad4a028b82104101a62c74c67d0202dc5f33ae10edaf4a0b4595f5c483407504268e706c2ea8900a1b5d3a999e656514e1650c71a1833ec8314804b830c9a2eb2db2c4a6f195b5ee06bd174e1eed48f9dc775de0867343de15afac705da44eb0d0bb41d8ecfbd45baeedb2df5a760b016dbb399381e4fa5e735a6357374506e4964194067116fa873f5a1c6b2535c43ce306b2e04e56829d5bfaf42eacf8123ea6220e5a541bf0b87885b82ad2f6018c976fea3e14bcee076e91ffdd9836a37e8c14cead2a53d425f940a4b85d75630921c88e2bda092e8394bd1f0ea0e4b9f5365c107d7a08eb8c1ab2864898e602503e000b1f108ce599ca1c2a4080ac8aee6fc196c4e7c534189f62eb039d1bf1fc71f86dc9321e53ec8766efebb6a752e6f68f6bc0233914cf97910262222908393501ac9720e4fbf979b496d86122e4b18804da799d5ab44babaa1024179315d54b8ec5c130f9295320bbc41c4df7282d3449054e0285bd727f6f51499694f3e3457206f7b546dcfebe61fa6c585ff6b437b189a131c37a0c7d83f1f896a0fb3d54b0ba71bbbc5a0f166b2868a89d973b9150f154c9ca9e38a5bf023fa2bcbedf62430917a722187906991ddc6e9a4488c4796219ed4425be83a7b73a6a9472fb31c98b1c07b5c7da4222cbffa441e2786841485bef530bb4eea0a502f8bea833c90100bbb92374e4c5f5c866dc2ea8e429d66323c6506776ca05d4cd9e394600f15ef9071efc088549133298e8d8f3d32c6d78872c32d772c9dcea25e2216960d27d716c90b18b9b43af253b74ccb989d4c93f489157e24d438dee1f7f3de3dddd7d7f06055d92be0dfdae4d53655cca980082296ef3dddf33cd57e675c23f1e5b2d70625675b26dc7ffba9ecbb8497148a7dddba36559bf1a74cccde1f72ce2bc4db628dd4e1c327b63a22a5c31394dfddf3663c2ae8dce4a8a23ead794fcad1225e61b94ed0fda9581440636e84c9f9c80c9f59dc9036b88c53d548a65c88e194f229bad40ca60d567b9f75a89537f901c81a0858f5ebe76c390308feb8ba2bab7722e7efe01cfe5f5ff9127439839e7aecfcccd2af8eb48c9b18f2dcd4e9b849c6de4bc0dceefcf6456eba53dff465043ed71952431e309909da1a0f5794c30b09283e547ddb8e667d0c33a13fa1d1b65adcc38352deea0526f0358a0398955603365848f706094be840666cdb94406188733fc772242651baaf6b7d503afb048f82358dee97e186d573ac223285cd870911f673402bb8453cbdda3ec3a3cf9e79710f3a74d2f4aac39ebcb76d82f77fdd29e9331b80b91ecc02f05174cfd4d8245e385c60ebf1728616ef43221df285ac951d772a3f758141fe7887da25992dbbb244a8d7ab3b46cd4e921b0b5841408569f19f9a6250564fa457ee3cad38c0da31c63744bc909fb469b83b16ce86780b2c25051301a91e39f0ae26518c083dcf48e49423cb38878b2cc71662cf4e288b0f69a0a5a943852e4061351ec9e1b91a2e04d6c927811bc13954a57b56eebddfce355d82d05b7cf2ea3607cc1ed3be04d955c46059011b89e6251329ff27e82ccd5fdac5d099e370e26433f5ddb4f3565dce46a0b70c4698448b05e33313ec0f05e620cba7921a2c591834979286978b965bf7108e3050c02e0deb065d87d0a1ab5daf19bce4f5a5cdd465f2add7be4e9f883ef8d9b59921e914d41b63da440752d9b57a6023745771727ecf5d890ce6a044a7ccf363db329cb013da71ec58666c866a30e81f0b0b267e61b5c02d71c7f357332bbeea06b187227cd6f1466f4f09c9bacbc25934c49d27c11cbaaf155db7aff8167a99275f632b70bc75812e29bd7ff0fc8b117ef45074e6fd3c5df43a3bca2364f93dc502aa2a35e88a6a10e98a429a3139e9359f5427365206ac04a49f3dd0387a8db2ffafa8bfbc9e0ef90ce344290d69d66dca3f9874b61eede388c79adb865bb1b86944adaf8cf67b0f90a9ce322fcbe5ff513bb6c7587105c96e80b363ef4b3d0688ae119a1baa4abcf290f9b485521a3124614c0c44a3fbbeb9a4b40323ece1cc058803886a8ec430379861f0310481e01474f979c060a2071f4132d474f86c80199be414d538183a3c4e6e7f1fe2a7174c0cce91b365d6a8ca3d10511497385a1a4caed0000000000000000000000000000000000000000000000050a10131e242b34", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "ece3b19ca351b26dd4d6cfc44ced6b8efd79355213b3dc4b95002e2d171ca175aa7c2f399e52d3675a9fc7464e3eeec7032e540acad1627f60bfc7b8d357f6e8c57c37041e87cc17f981b582401171a5e6e725ab930110cc97658df317110e0527612e4bfb2a5485ebc3dad8b5696929bbe518a526922e4b133a55a669c77ee20fabea6cdb5f80b28cc0a12be967cb5c359d34359cca099da2b5fb175029c4eb18c80a80937b48ee3130f8bf70565188efcd68ad0aecd996560bc20fa6951b324202c52e37b1b813efc96f3ef75a5091eff3d50a7e007b163de2cfb828df3b28e3a5bae975af6a534ea5a7ffa756865b1de4d2bca8919c4ce2366d74af17974c76652044f3f1d44a13c731adfb25541b398ca6db244c3510289622b263d6dd7d37019d3305ef1065c18254a4502513216885e91d0f1266c60f787cb025f2a3d82d31153732fa1a82359ddf8fc614c063d90b3e3d828138fc74abfb2bd59269b16235794d413facf46a508d4c675e195b7622425a19f15946392db339e4e29b280680bba23990756b7f29e79e418f13f0cdb9c509e6a37fe8189324c4d7656030814777ad80e861e0e29e1b2b0540cd385036cb8de2e64f0632631c03fb0865c1098e11c36457d8a5448af4698b4da60678c73d83d1341cb685034dce3fa4b3aa1fc8eafeaa985329f48594df01fd82f936c60e8018b428bb5ddc3f8debb23598cd9663a3a66748945476a8e748edcf97dcfb3daa4fd8fcf76d741ae6eb280ec751bdf07489d2bc77a56ec6d1bcf7f3dd6fd9ac456987abcd612ab17e7be368f9803512d2b5125b46e11da3789fa360899a34105588d4be0fcda2589721c4d2e53b4b6463b92aeccdf65b4e64a6f978277c57b8675955037a580f29016953381f2870f80a23a379cb4fd99bdf61053882119dc5d6fbf86329e724c85fcb6824643b2c2afb022dacd76baf5ee83c58fc82e4a788bbad97788aa3eb6d322b5ab2de3d4824940c34d68bad5b56a851579c9a39d47dc9224703be223ddc212ea4491c5ffc99e9d96dd450eae1b1988808b5c60ac475e50ecc2ec2cea83022f1282631f98ac539cc2c2b488e0b91cbff0ee1f67f4685abb60a0fa11d1cbf972d4d9753b4490683c8c6ec8e22feb77c96bb2f2ab9bad248079ecebc99a659423b7a39635fd1afddda011632cc1b3c8ac6ea4aedffb1297b57bb099d55b760fcd22a79fde59c9d76c387ab37d59687597c631e36c83f5872c57ac1752b0b84c5cd1fa8d61380c0e817032d902c5a2d5ce8387af56aeedc95274186750d84b718db6be86de771bc9c88f68ca42cbfee9f3575174754907be9982aadac749484d4ad6ec9549c1f7cc3e1ee6fa7618de5a9f6bf9b4b2117c51aaa7eb90d1d87d779d339d3fee5d0a32f5c9f612285490dd052719666ee408859aa4524dc75a58695ad8e6138e3d4d6ecea0b96038a4aad615267b50244eec63a0cbb4315d077c04794a3ac6d1e1ac19283a411d08365cc49bdc4e85215e201cbc05c30196aab8f10cac2310ecce67da9c265655bf5a78d9c7084a99776ffe1a16b8d14da08d01661e84d117b5536e55004f41d727c1de4124151e26a2c10e453fce81071f73ed8ce109e11e4cc4545398efb7dd9dd39bcf316065f59556b223745ef6fb1b6e9bdc4cdeda3e95522a28a0eb524b0349ea0851403ee635d2c387af561760ae58860cd92877286a1296a942bab6c0866204d0036d7356b88c27ab48215d7799adf2925337357413c91cb38c031bfc0f1cdf721835630391e197dc99788980a8ed269bca3dcb57752442c18aef587de94e88da64b128cc1bda59a55237d9969c9dc4c7939beedab13a27bee96b1dfcca3710176b4248e8d19fe900ce48fd73fb486eadefdaf4d17de003e0fe82f157d305e1817593de69ab0c4c7dd07653809a4f437b6af37d4d571d80b65066f45d1b14f6c5dd7c84af90cc9470da505da63ea1eec5dffb17ab2b2378a0778782d697cc39614945979649e19ed2f756ac1acb87daf7d80b5586a67d7be607fd2276a5b205e6d153f6ff8fb8c877018bbdb8f863be369f1743cc3dcfc21fff542db62732fd270672f849368649f56176a7b078494868b59fd535b5c0d9cb92938e5ddab217e29952ee03068dedce329f5fa9604c90e177faf32220851a4112910e1f3fa2943aacca71246b2c871b8982bb5d0c0816c9151d9486e6c04fd07aefb1057703f7d0acaaa3d417cf9c69144f96591329ae3f716ce7c65c86192a1bebfaea0d60921be58c7795b61b2de4b0216ef9f47980108079fafc5d23dcd1ebde3f53915b85aedb1184cecf731c9124f71230994dd508dcfd7f571a0353fe336dc9e6e33381d3c18a5a13cb02de759d6a27751dd3573a8366fd1eec12fe5a4de1f861a12e511b7ddcf3bfcf600661ec5dfd36480c42a6db34ef58af783e85f5c13f71136086908aaba5a71d984187faedba9040395a1a2b921dbb5ab8d566c6812fe33bef7a2bc75bc8965fdf173cc5118af9a87b5cbf1a83dc0cf3f18e8e619e725d1158df5a61d1bcb8e3b4af6970a6c8710deb50473bb45f8ac58ca0a2b7c2ea1abaff0b3860a92b07f9615de5ed78f91afe26557275a067872a9fa01240f26e9d92197281320248c36c16a643b52f3e4588f967b953d70aecca52c2525541424228f3f355183eef25fac1bc9043e68e1e55497f6dabe97484215a9e17850e42d6c406e960d4ba0e0d51e611dee19d901186d347e15532c3f34a7c1cd035043fd16dfc3757652bb320501dfc1c3120e7f80656fe3247fef472671195524ddaa05860047ae8fc00252e6e1b8554e62643a78bd2873de2791b36fe9d44202e1e7f28fb504bf72d930b8d4722d6e63ca67685da52acdfe90e4ac0d6bb01f1cf2f5fe7164464b004fd30d6de46cd9fe8ce9c415a80535c7c035da91b5a153492dce228fbc43f61a7b9049679ad4dbf3d8d4e14240db9af7e498c3a7f91d76977f4f4dd101b3ec5fff7655640019e07b145a6f9472d8134392e2bb1187f407925bc37b76344a3fab2a011497001dcb2f9ac1bc3f9b0c334f048d8baaa07a6c5e6faaaf110c05504bf758a2100d5f4eb4bf2fb3d4b76a2c569b844a98f6f1c54ef27bb9b70daf9e582bd12414550103835e75ca097bbff13aa29083ee718a3c7d97abc70ae65ea4cacdf6facca7a0d6163f8a3ab62665814ee7cea248f08327f921052aa38ad6fbe4fb2f0ef36acc41e940f2a3fba068ac2331ac8ad24e5067ed85add60c79e2badd56e0bc8028c1adcfe747abc8948aa80b32a6e87d582e0af9eace1ff641a7b6f1d4143a2ee135b8dd7826fb68d2e733303a1292c89eacbd581de1a626e0f8ede5763c7f88c8bd9c56d09e5623e6bf9042f7366b2ec26fcaf3dad17f78070a3239790ae8fb10c643483d876d348e28b0743a77574e3837c330098cd9abd966f982cbf1f31cb2866723e429ecb0f10bc6c1f00b077c7dd52c894be987eec1c0abeb806f622491e59464af56e1ead5ed50c21eda0cc906ecdae60c5653c753dca29bbe8cee1b162d929c0af89669ad1e5d2504e8c658752f7a8041d2bbf89d5d3e00852d8854290f2fd68d8af068b71220225153554e0c340471cc0e41d54fe340a2926a6833df072422e3920be6449cfc6f9d11dcf4", - "tests": [ - { - "tcId": 73, - "comment": "expand_s requires 30 SHAKE blocks", - "msg": "48656c6c6f20776f726c64", - "sig": "7f8662e4172d31b7187a2a58105511317fa23222698f01aea1bd1b0970ceb5c510514a14509c0eb16b0cbc8c37d96b487a303a052bb92ec2e440fb0a99adb3e4f2d6f0679628cf716462a4d6b9160f2eb2fe0d11fc0ca75aae5b63813f4b16e90dc83c9813285ae0f5bb76a0c9b1652b9cd09b78384955e2c4e41cd4c4667f543eab6a3ab47343927d7c208e29a24d4f17b94973cd341998f1107cc7da85ee514b0a73ae357f00e4b9f5e80bbad76ab901ce943bb82603df48c17c7b0818198b9bb82187478107f8466523385e18434b92b91802b8c5ad3b67caf548822e59239b67b608400c78a3e66ca0d78e057f17d1b36b0aef12e8fa8e4056a4ab7f4b115489b3efe8e60e008a301ccd3b155d7e955de6d1dae17612ac14ff59d9f3925b19c12351057bfceb7f21626cf519c34ff9ba62ef030eca1d39706b532170ee14aebf91cc27d5c4c2af2f2c218b48627521985ae29cc4ff554cae7e4f1b99975f89bd06be2311307e413401ea43a6a27e8bf2b7f865a67dad689d536aedd77feb68c895b5682f6207fcf28f9b64b7b87aa9113c3eddd6df3a43bef1ac6f9ad74f63b78c245131471d8f319bf014cd4b3e5ddb684db6822026fedd2b86bc7d85a7e9869453d0474e834f5843f895fd9027b0177cdcce424ade7df90fa0fb7b3464160a1a9b669b2b7bec486ad25ee32080a2b537f3a7c0dfd0362d89f1062027624a28c2b497928e9224e936a29e90a5edb4a1511399ab0bc552edc1bd297d319b73c58b8c039bcc044a96e11c8115a7719608fa223ac8085a029263e1aa45c848e3560119a61bb65bb7a1833a26a1aa77c7ba7d730983cf54ce947bfc8e9e68f6dc8133bf7cbecf3da8f77ecb651c964a36a5f5dc0b8d4236008c14ce003ca01926fd462046a90c693d7f0ef5aa25d04c93caf440ad39106bffe9775eabeda99b1e76465414c2213c4af16422c8c3d0b7665dd2b627886d79ee4a83b78c44af12208efa5b15e56a528003d9139a377dc0ebc9ee4c797c431d9e1cd2ab7890e8cf483ef9337eb4d3f4fd54947c61b73fb17fe2f82d9ee998e10ba7c4d40b18fc885947372912baa5d06635e32314b713d6481d0760ddb596cb0c4de3541bdc6511d352504d8235f5f98311c6fa2b2dd7bf0be38939e6e1e170b87cc015fbd1a6a575669bf38b6dcfe967686976afeaad2f50474d847fb9e4b46d2cf0e0cffe12578648a4727c21c18d39c84eea8b0c579d09324031dc35a06e6225d109a4c37616cbc01ec5cf3cb9107e28b175984b534ab32453082cb1a22e3c209c8d6c0c55d94fd6f34288994696d8447c756280bb08024f4c94a0d3215eee50e3b3724f35930200c89b29dcc57fde757289f048fc2bb86f2434af1498323ef4a8686af5b4531ada2131eb7e6178de9fef4a29f36476d60c862d82c8e5b22dcb936c808e525087217649a75f8d038de917e0394fd7c0bb065214861e7cd72a2494ccb75d1ab85b63915841a8f68d09dfb8663d9a689edcb7fecd9c5fa04df8f2230150cc5472a43d8110b5a176ba387fc2bbc8cec80c4ce8561cf6ed5460032569ccced0e49e23464f6e54c34e63f1e7c777941ae843381b9ba4ce96422b1a0e999ac3f0d9b0b4b79fcd01dfd0a5f0d01ab3ee818e342009453982aa4c584e42b8efba37d6e0e147a204eec873f36ef0478dea5ba6ac0d5679a69c0f3c263fb195cb6fa106915c01412d46b5a7be7c554486c43700dde4d84e3b4b21ea7a8c1c03a388ff9e545654c76af04c291e9560e70f0b5a20895fbb8b8ffc824fcd4a700a23cd88c892eba03d1720d4068a1f5bfd7bacdccff61ed32b78f8614393681a9fc07458ca0ab2d2bda14bc03c0caa8f7c49a5969a34ffa0a2a0e410ef0eda7a1a6704c767a5d454edea11de3fe76c5f0578e361d09b50c24c1d03b7f611004aa0ebf6c53ea44f1d8d2a98e909efbf2cec7911b64afad91ea207b3050bdbcc4f374f478da7506ee7db97b98ca8549fa6d26fab52ab71dce4a486658726cb4462c88897ab78f2ee702a728e69f9939af7a508ff2674d90a7fe23c400af5fad8c558af502e4f8714cf5f1342bc4446c9ca7b66604f20da76877f049b697323c8ed55411473490d5e8d33b474afa7243f49f5ec051b544f9d49ef75fbc1c27428897ae0e20a11a76c2ac9f7edca208b17e520d002fa535bfd8de0c2bc3586a0ff487e011deeaf2706e93c4dee2a08cdc77240ecccaccd73ecc014f066d41346d4338452320ebec64b20bb98fa285a0b67b3cd904d0308e8db017e1673603fb6a00ff59da4b0403d9349b93ad833d11b79acf2a756105133ff91cbfc14330231940008c2b814af0d276a1b9516e60b1c459fe638aed37a61b5fbfd2479b96b617a873e84925c26416d3930c41dd82b1fbefe72f2b67d8163a600e521d4e0ed0275a7cadc179d375b5ea32d3a3f89fb57394de751125a845f056e5da2009436a60d6c24e9bbe5e9b602cc7a3995910438a7d56436baf13dfa0d229a07c5c859e56fbc4ed2023c6762acaed9906e40e11cc9952f44e88955058cf5707b2a8449a73038463abe0f2f5b203df7dca47a182e964abbab5049fbcf4d9fed322865e6e555415f6481c7316f94ab99ce9642905b3d6a7f8854afae6509aab8949c9362fe842aef42c86cbff0ea4f0c0f8b479ed133b888a26ba0285054fb4c4c5e36dbd8583d5faa6ff2c9bbb2a1a3b91c99a7ae2d72f02f8e5dd80eda3501bab4f350518f077fbfe2d6b3889a3c0cd104f3e7b78ca3aa7bed539df7134709ab6a2cc7548ff630cc46b8a9eb79a648d06e26b2864517b81a2f8a9244b6f743d645863b6cb0d7b7b5736c71b70f3713a61683cf00e9fd8d3c020a380b7850d08c04b9b20abebd7fdbbaadefab93dbbc8c4f1990789f03082c0f6ae05b018466c898ace950d01f5b0572ba0c28382bf4a591b0830672d50b75a9b353bc50f3b6fe7c65f52a6fd3dec71325f4f45e693f8e76430fbdb43ffc4886c16db832cc3a13599564ebd061632b4f7c0ff73442a53b2c54d1de4c454e3962070f73cce584d6770cb8a735904b5b241e658df5b762b91956dc62c4246671c3fbf4595f9051b0f1607e0a6f731c89601e32537eabe9682d7106d43b3605cb30e5d2c9bac7345104757b9823ffce1601c01e81357abd6e4c3388c5e01b806ef7ff2f53747fea3c9bbe00ffead739cea49dff717f664be99599255b76ebf23c60aac6b8688aca6b920967d5484538aaa9aa699bd19256103c09e92337487a3effa71f19e46759a653e0d00615c485f34e987994a005db3affd68bd017e2786fdea57436afc5c86e0638493be16f1d68688101eb746abc15c568211de833db2a1977672755915fb0dbce5903a3ae197055eec0648b717dfff8ad1e409d8efec9c86c455469e8da146d7dbb03141e0c33e5bb050e6bccee6067942d0d692237898722044c5655baf10f76f2c0d3533e87a051cb7147fc3e4eaa94acaa102bafc7b73d8f2edb41a810657b57e0cb7e7365ad19fddd64b3d713b31917403a92c48c8578721b3706a38a2b279b74a7b29c9d4caea4630fc323f009e3eb1ad1a047066f301bb76e2fba2233ce409c9e1e5fb1c561fe9f5d2d7c5c181fd996022f28cf184de1e5415e04ebd51e3c186262d3dac6cee9872a4eec41b414b2155e657c9e0e50e8fff940f6677dd90ecba42508fb514255f4091a587186dd433378ea8698a6f68977a3d50a507537b529e094a41413890e497eb30fa1dd69b2820d9c7d92bf34ea56cb7fc79999bf6a1f979b2f4fbdc0b1f2e954b30cc06985e9e2e67ce5490943698051e60ea20410c60ee201dae2ecd67174d00ca5ec464a81a4c6aed343c7ea79988779d3d033a347b3a0e1c01371fd9b6eccbe90cea9da1c624d49112944ad25a74558cc05a0813358be8667bf294bc9b6aaa8fada305c03b433fc42b360a02c85d3f9a04e05a9e22242df49b178fe7d9dc5311e7cfa674b9bc87442b084ea68a5cc2bb9cccd017582edece8314ffe6ddc82293f6559093afa57c788c426813902fb8f61f6575a2ca12645ed69cc54f21f42aa1662811e09d989120661030173da007aeed018510dba1045b48232ffb663f3d8080afa61b831b6b295f6c56faa59c1b7f0cb01e7c1bf1f8f493c10b4a23d8c25a03b105d7dffb677fb12401d1b06096104f600146de1267e7531ce8d7c68cd72a920e52a88b0117a6cfa81ca3ebc6e00c81d38281d8feaddf10d377d36769e1b7aeb63e84568ec4ae8e24439c4ac9411345c9bd696f75bbb17d7b011bc6803fc44cb23c5d9416b1ad2498eb18adfcff86cfc9e6021de1d4896a0ee9b5752592d030d7e0ea7cb05d214266f10a088c04253694d626e33298c1cf1a7e7b50f060cb9a4dffd1e8442b2f02a46de2457e33626e82ccc25df9380ecaea9f90ceafc5c5d9240c096abbf50beda677bd997a2575a8109dd458e7813a401e3b9a6692facda7d4c6a6f09d08c10e229f5c78fe78e4c7ea8149ec4347836b537d50fe865fe2c5ef4e00926f689f55ac862ead465bcf3d9ad3955e5bca6713e8c3e91ab601504ffa3dc76e923895e7728439ec258faeb422bd9be978e732702d4ac771ba9735ea09952444740388c66964938e9ee62bc8f1dbb81c5f0c58ba6e6ab71839da1f870f6a2823a4d1e9757b3c1d4f23512825b99f92f5dc9f907211a71e63144915188149da330476fd89c5fbe9f008ae1011197136d406c4117d598c2c1fe0ac218cde6ab4500961c993eff6d3817a284231cb507b9c5a329f33429c82527868b0283d73703b9f7755ac34a0da2a40d2634d0bde200afbf58432565ceca6852873f7a1228b5378976d6e7643ead35f4c42b3376102fa2903761f4701f6dee2cec9182b7e873a66fa84ad2f67c8e065ea3e282f3e060dfed15b7d7f417baeb158207c4bdf2af95c0217e3b878adba8a550dea03c6e2aadc88e50a3f1a1b7f61be560bd8916d8154b2e17a01cfef4d2345fbf9a0d644d096d2877bb9cf97b2e058df3131669a0842531f2fa59fc0dcd4b92786ae89eb745a5403bb7f2bd1da41ed50089d3aa2671505960048dbdbd2a557f01b10fc382ebeacb2ca99c6c8e30f98b30119a95dc0a821a8e63a6c970c148ccbc7e5730fa430d7509ca91f46bf622d047be7219867222276cb6dc57e8cb70bf38215ced485d32f34d1e4c15280869ec5c6922a1d9480a8c749a5c0a5c62cff6e185f446d8398e9935d8bbbb73f70225cd817f4f3ab88d7e29f7a75d06c680318fedb28f8fda029350c8572d4eb04b6a0fee63ee96f17897d87fe2a7372f3d0996e44abbb6e61d6b570dec13c640c189de00fcd59dfce405b627d58d2be70448da86a5dcd275613bf435a15951f3d413eb1b8c7b3e0ab7400d349860f3efafa6f7712c679d5540b1fe8be881a3af8283dff1046b5769686184b1f25622f59742fab02622f7550c1a034c85049ace07e309a6caac8d2c931c2202cd7a40c8f480272f770b6d7f97344ad654fde7c1f8c56f3267ff6349c72ab48cda80eb2f40b6c03264ad46cf8f1c3bac8155b20ab3db7a93e41d587d6805c6569399bf07789c8e0c0e84ade84a2cc1a7d611d6efe0474c429ecd9e1fe0d952258d031333e5970f18ca363f9a59216ee5ce2def69d71646b4bc189c25435face425cad6dfe60dfeed4b3ae4c420c89c40f9c9fd8a23f610d0249df36b2309085e16adc90175cd7b42c8a90fd0f4f3cf75376866e0ce8ec8deed8ed65711a7562b5d208f9425bcd04142e722411d1de491f21b3d18a380166446530e55944726dcbee98a4e789757ef3ffe3b85793b8370918a596d9226428cc46ab44e9b12f497ba995ffaf16bc17e855bd4189104eb1af6de01ed700dd7d6a08035a3d2b6a4558489d46117ddfef7634b07050e687da30b0a5c1ff9bdc00f99bdb6940e77cd76d481b359b7c1292338e49a656336657f48aba72e855a430e27a0033be7323926df919455b82c06eeacca049278e40ee85d142e509c3bab27f3a7eb967584c81a107e1e422f907c44767b5b30af50430aa6c21973711ea21021641a0267c56dbbd0360980da6f61fdeb2b180bcd51fb2587d84e73df8d937f1d130057c1138428281eb6aac38dd18a163ba7bced386fcc44abe08a63a416d0b6cdb1e8b9bebf3f844ca95a4d193bcab776c0227103ce35c3bdb2f7b3687fdf125f62352b6028d4c22f519dc6deac26e326d0de59c1228bcb8452bba4811eb8daece06b4a60884a39525e53ca2fa4a1d041cf1b7ca2f66b030075cb1a85b7bb7e13002b491c41cc5105fa957755ea63e3ab0ac0ccf54052dd188cfd1183bb5a52c30d27f71c1529d15aa02356f3360fb6be60806755cfd410104f06bf0e93521fa9359bf70cddbc9eddbd9de76491c3a7ea7d21b4d48f639cbd6e23b1e20308354a95044cb21f3d4a567b8fd10a1d778aa9d1e2f0030979b3f00422546e8488af050b1c2e535581a3dc0000000000000000000000000000000000000000000000000000000003080b121a1f262f", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "1c53bd05d8023947b038c4c9e480709f63761572b5ebe68a15c7d5ce9d2767d88d9cadd45f120865dafbb2c6295f2db982e87d3d270fa6c7f2aa4ec4591f8afe9a516e675d03f3400bd4a00060cd8cdc704faff5eb1e7de1adc6e46f7c6de65fa0c587dde042a892d876eafa1ec0628e79e006117cbcc8c0d7498e77c38fb162a7ae27bb8b014f91dbb1f30e67a43504e4f0a7195a3dde5d4b68c396a4434f94995de19830ab02f6455de4a323c56f9e3583a3b98222aef6dc2c87105f0f25a86d85ee486f3e72b94cf8374e1c40737cf6cabf2a23baf2de65dfeee4afabf0edf399a83b1d2562226b7acd0163387e02de589bc9a04012750510921b7221271c362a08a07244efd1ddd0b5bfe2a4ab03243d91725bdc36e1b158a5dcd8714d40e61e440a3e2981ff9276088a78eaed7dec41495e72131ed420767259c71a15fb5d4430fc21d536d082fe013c124b3ec480e26dfda1083a085cd16b70a9a310fcfe4f51d026fede2e0c2f874ce1a19b020f53c3c6f11158f7433ff7ca3078ff4cb3c6299afe4cf6df32e43895d4bfea0f95d578a7322b87c8b494e8a8a96b8d9dc52585bb94fcee58ee07ba6742021b1a42ad9d9778a092e8ad95b95346471ccd0c7c9c62b8d29b51cb3403237b33ca0ba9d18bca32ae318db0438445dec5c074125d76424f830ead0eb9c59b821970196ff3471ad1e39e2df14935da3c432563f80c0f8de97145a8cb4ce4cc1e918cf47f01f09d91636e24e5f741261c857982fed519569679bfd3318d7a787b003a5f0fbe2f3668f16df4ff6eb32aa7702307fc1d66debaea4306eb859bda77ff8bf0ab99fe32cbd6a5997cfe7dc2523fcc4f95a563ad26341f72318652516aa647079f3db1668772e25ed69e186cba01a3a5ecd018042609656ce8f2fcba89c959c3342ae3ba12d5b9008ea270150876063af0f858023be6a1238ee7934c8f47bb18172eb3f258ea4a42198a24e8b1a6e61628b3be46aa2cfdd0c5eae808ab21a5e1c3f83fdb5bd9110ad2387019caff71f3e9381dd8763ba5887225ef6fd1006f09a16a877da40751d9c6f8458782320d4697b20f817a72678d6aea7b7e0a7c3b9c27c020d93205564687f15622b2ae210d7a6444b7da5ac11ecdb2ba50c417100fe2efc81d5ddd64fb7d29bdef20b9251f0e5e8bc88b59d7dde67271c3dc6ab0a6c910f9763db14140757ca1f956decaca0da061416ab6971e036859aa614c77ca1a9fcb1ef019e66c10eb932a356f71b31ba648aabf0ee6bcee6e7cc62ebb21593f200bfd0de37f4c672070894211bb0c3a9bc59541c74cd17d2c8ebbf6467ae275ea85c5e597e58823114078c4e2e6caf8a429023a82c643411184d3a28e2c5c12e7dd4f7f066d46a367b82570d69b273c33ee9e868f44c3f70905192dec2dec0d7099ca2559fddb665c769f6d8e4fc68f3f5b6ac3af88047b8a2a966ee3a6eefb1f22f2837781415b6ffe5f7a654ccdde116b478e9a26b0f80f406dfe405ff3b5bc8d1b9f3c392fb391c9282fe28b6fc480ab92dffdfb5e317a1af287fb4632cdd29577b970ef415a542746d145154e2ecbeef56bf72e4184d8b691621dbc1614cc223b46c80f512df68ac6cb77c4f7cdc17f4f15301d7fa4c6825712fd65e46264f121f5c66d326a1c07a7d432864e112ae720d38b1e15de4e634f1b936d461919b79f4a470e1871e1da49cc5ef898233ad893d3a62386fb78d1322b125506282be81c8e731d7bd7430bc1daaa381c1ebdb2826fb52d54749d3b4ccee1f5785c48dfbc92bc9061ce97ae846c4408d518233fd1ddcce3fbb53cd814ef424fc8829316b7f13604ed007ff7862f90c85a8d5514684a1cd91fcea2bc966adc8b6588fe4619c70e032736690fd0307e9a5dfaa6fc1c165a2e9d5e25ebcd573581f6b32ff574af14064149aef0facfc14d1b9de7594103aa4894c5e7a95ec10972946f0077f659a3d5f085e0f7da7f73ac5493a1f02a2a97ff9d2fee59907a4df2312f431d1752f71ba0e994c5b328cf947a5f652778bb6cbcfa82203df4421b740acd6914cedb41853c0170b82f536c4ca6bcc0296456a795599cc4104b15606abb50c368d3abc1b11a80612943cb996d455672bee2d1779da62c4cd25a2d40fe5d620af9fae092011c6c10518215663cafa5ff35f2edc70d5ead9dcb74fc288d774dbc82b4b0118e11ff3a1a1d05cb206ef6d7daf2511fe67c61b08cb14e099339cece82d030fdc3fdd045d517489d7a481b78dc7652bd51aebdc7e1c190cbfaad9fa97a422588106814086c53f31c49a41c9c4820a5e3a20e53fdfa61185e50ac51d4cce66ce28e975ff5a7c29963eb0793c9e1f6a810074cea378444ab955232ead90f563e5042107c299928d201ff74313ebed06541f78ac84a5a8b5990de643912536f7e9ecf7729d6ce241e1084c2008bc0ccd6010be9253f2edf2ff505e9bb65e642d9bce704e18785c4840406257564d77867c8dc7d253bfe5a3717f8b6cd6e1e7ec8e44439f3489241b4a3cbc6c33dd739f3e22cd89ca9a437452b6b1bf53dccd4bb08764bf1218fd0fba56f82792db64eb7e129de3fcdfca093b0ba8e5e5225ebaf3ceaeb2f0208ba360fabace10a2f0e3d5009979912181dd6c4726d09f55d66766306358f58cf3537c8496f2d59e001d17e087f568dd08931e199eeb8e4faa53e7d3b6876ef946844d2ba8b9c10f4fe5e77a4eaaaf5fb99694a96d7e395a9d4548e3946e594a1e15297ea8d6c3a3a0cb18657963b2df43bbc1c97b93ec0f5be715f118eabb2e7c33887126f22e591666eb63d1dcf5a12548c27c9c5cadb8385f5970af3e1dc1a23662bc0fdfd94c79d8b9c15c518aba853d2ea5379914bcd1379b55d967cc4f26e7e9327efb322a5790cbd038ecb0b829fac69ab747fad5397a59c9d2c9290decb8ab71fe62c67d4a04bdfac56130ef3a29efb40614ed8320250472db44aa2f3c3d5f66cf5f3293f15e39336b9a32f4080df7891808aeeeb3a8859764bd8ef5c586a611152c2d82338213b2f1e46a67fd90f1ac08817abe2a6923df03eace05cfc3920656f3529705b9d562744b114a62cd1547c66223f876ded8da794f97420c7c0c530657f7fb41a25bf4fdb61be89986cc063fc7461385ce46f20078469b901105ecf74ebd3a167a2f696979877f27949ee711c405d475c7b78f9295bd788973778c9b53502e38c2f1c50b948b86612374e84f0e7a6f8c4e444283d6600f0c81c211e99b3bf252dce6fa027065e03a5752ba8499411b4cb4f4ecf33ce7a4810b86a4a423898a8c9a227db7d93df2cd0fd9c4e9a189c371d0e8085a8d495de0d96597b8a0eaf66f82c820383823f7310e44148ef407bbd1c9384515ae2fbcd45bc8e84c44c6ed98913adbb638429bb8ef633107b1cf8ed2b21de1d1d6232c7f218488200297ddd02e552f8f8546b1d28006612165af753a5e4140430d66d5ed29606235547f1e640595c1abeb2b244d062fcefefb1a77359e22afb4f90172630c0fb0cd76318d1c0acf336966b4fcadee8350d007c105226aa6f214bc66e159c1693a59ebda5f67c2dddfee8ddbd0f8302b51b3443e27d8c1d8dfe5be41dfbfb348e023a9155c59abfa9a59b107bc785d769bfae081f14854c407cafd58532ae7095dca4", - "tests": [ - { - "tcId": 74, - "comment": "rej_bounded_poly (sample_uniform_eta) requires 149 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "3ae903f95dfe2907e6735c88f2892c72d7a6714648aa1819288b09ff22d37cfe26335c89342fb67233301212cc6612e91c120362fd1cffd3a591c6ba8f03e91cc7402fc4d91c7d0c4a9d557c4dc31420636ed8d18fee1a8077667776c7af390148fa3e5734ba2f3f93eb6064b035074bf73c424c4d75911af68a3a870ff4f6af06e59fdd0867aa6dff5f6ceb2db94c5505b4fe6165297ea1828d8c5add5dbef6058bd1395acb4714fd52cf531639a7c3e90b4373c627f525394e57e7cbf22edae55c3fe8186a5a80f7aede40defcf855cf248ec9fd454c5630baa381c828a2a0103822e4ec78aa229276d55783799933f6c83bb6535fab6839ba581a2f2fad03fdf1d01935f20ea160f4fcebd17aa2bee938e2226bbe1386d2f776989a070f0fe5322a8f5352961ae574daf4d1f453067332548536cc95f5f201a8ba91609ee0b7613dbf5efb9257f38a46bbf63cbf97699735691ad7f3ad0cb79ad0ce509f7356654496c12efe1af615228d15a1191a587b2039d0ce4e5b287b2076ad220552c0298532bd66f6f1020ce5871611d2fe59254f1cd88608512d41475264e799b4a2d09218c6d02685819852343eaf51bd65f73153e611794f65a17d7852eb82b91abd13261e576a3b4ca1705fb378903e1c33c69d89e53a5fdda9bbc174afe05637d68af453af1beb069bc08618333ab6190bf5d1b67a8e5df06c91d84f5e477c4042ac1e605135491631754a9aec7261ee911aedc2e9b45c67bc597e9d6c23573981c3fec528e7f4211a0a02428999d6f429999c37e904ced98ee47fe3138268e5bef8543b4d6fb4584ea5c13432f44836cfe054be8292212b1632fb8241e09026951521bb298af91dbb9f992c9f5c9eddb60881934f6aa1500f298dd30a0cfe257ef64d677a49959734c4ab974bc304f8a6b6388315fc61ec80848e41c7e3e45add26105453f3336a4322b9ea29d5ce7f076ae27b63f6d58d7e345c7f13c18e7165d9a85111abfec8fc992f3cc39bacd83d161300b1cb40637b2c5a8ef9855a7e55f280cdbb9105e279e1503fc5c338da59581de3bb4788fb1dd50b780f91dfd3a57276690816d58821df3c853c0260a9403648d08e2a2d2e822c4cb74893d9185206c45807084366162ed72a0c7f459a9c20ed95cb51ff904f7a4e43d9a450d645535e2e455363f05f2a5ac98c8a78f0f5fc1dba6c91b5415fbb92fe12ee89af8ab65a5682a7b366ddb84ca4a817017354a8069e104e81d411bedb08285305a13f7163276452d5d7529ac858080afbd71a7dc2abb3e8f8f66b35489ea263edd838e8ebb5db99f55f66bfee931a2f199d9b46d736b9f764b53408f1489cf93d1733f834e53e97940b033f9c36a7252dffc885dad2f0d1cf48f3edf7eb1d6f06612f04ebd9b309f347fcbd71b5615ccff309351edc119935ac46cb87b1c1a701cb9a9ba07c119209e3a72a6627cfbdf1a03b1c38d3c625ed072bb0fe9084778cb15ba5957fc96a6d1e9cf0af37b4cf35a9205c1794463491a4d1ae24ba41178b9022523ef51e86a8f30d1c39f6b894f743253cfa54b7a109a1d5ef831ddea52eb088d454325dbcfae0773de0e8e83be1c37e71b5a1e84d298b0a977bbba637c7e03f72b915cac3f21e86d1d0e5febf1b8e3b0d54b6732d4e5771a3473ac0ad86e484243738fe1b93c172aaae44cacf7eed820b5f3c9678a9d182743d68e7dac0fc55865d497dca147b5c160607147fb858919ede08e720652b2d72b7b14cf01bbf45ab5840c9be906849681bceb743f62b4dcfe0e52b3e02c12e057903a9069a571a1da9af10c4b3f3883ad3153fc1130a2c23a0c6488b26e5a350aec48579e2ec49f9babfff667075b2e019071d77dff0cac59c45669f581449399826a93ba85f6eb4ca6b173b0dc4cb7b97a44cf699d95fecae42e0fa3a469d15afa41607c2f5a4cd5c2fa15842490dafed68fc68d3464fd70fb8f7b3f66cb3fa3d73cba4913608b449cd73f27a128a30598c66826fc3bfb8784c6b60e8a6739c9a5c68ec403917216246fdb9e18b28e2b9f7b00b4b2779c051e434e24595130dcc705fa1f527e8da9d4ceca37add516d6763d5652f4bbf4f87cf3f1292896bfed8b5ff53247798e92902a69d49561faff504917496a7be084635fe5790ab46667e160d6555d221fc99e41402df79fe1ef06c36a8af9e5b6cc417ff3e2941fa943c9068888aa9fb756acb384ca2a2ca35bf8ae07948789a0e6db5f926ce8149307fe3b21c5e9f0ebd70acea15d1d69144aabeeb36d82840ed90e1e5773a773e0723cc4cba1694bb20913472b5f9ac562e8b98bb696bc6055cee4a6d87d2176fc87ae261745797754fece5cf20e5b99b744fb9936d2b228b5b2abffb65afc36a59f7fa71e896747ccaf3ce7a3c89f88f3ea529e4299b912eec10a519167f3896f4c675a65a1c153d50b670e12a54e9968c8a49982ef898bbd8d303531e673f9e44722febac2a202a5e66c766e48386a0ec2dd1f48cb0d7361af76409d0f3a5ec6c1f668dc946d9076679d651859e7f12d038d3ee9b744d1461135bba75cd2f6f1aaf37c1f3c7e153308a16157de5432b200ba26192e0991136e3f61d0728f4e6d41893a4eb1dbb0d7246ad20b96600edf016de6a38b63a48a5b4a88c3848e13d352f204b4001e71cc41bfff82faf158d9353bd683759a1de45aad0879c9dd39415970d1db5d5be96154f2ec68ecd43e5c6977a8ab666b99789549c59729c3f1250bd0b640850d8f846e5cbd8b421d5984b3aca48648831911b1fbe3e4a660d4d8c6421ebda73ef9e4b1cfb45c973f065c62a6447cc7474aacc48de78abe27f7c2cdbad97ac7d3fa151f4fae59c56939ab793f79654eac8fedb0523a3d6a8b782cbd6aa8667a36519877192ba4f1ed1900d559f52c6143f25a873002e53b3f33e4208072a55a8cd4ea8fd1de99b39c5c261e1fb9ce43d80ff1bc8ccdf9650cf5521dbf435461923864e38d9229f8b1bbbf850cd6e02e8a51013495f1ddc0ab0f0cb4bcfa48345ca0990aeb44928f82d5608159122dd1e9a11d1859b002b9914ac4a8a9c00e18d3daec77ce744bffe8fa7068e58e30e45d33f650b4a2865645d5a93326e058da9083f6c7aeae75f4671f811c2c666bbe508a8b0b126a6fd98307fa4c0ade5ed6952c4e80c17d0206b3943374a951f888f0ffb4dfa3974fcd8790a64910d6298f3a0217aa29711a160fe9b9447544199e80348558978639122c289ba6928fd35cb9cbd299d84ba14bed5db026df552cdb461dafc0386470e63b608194f307c976d8105eb25999304dd246159f507447a71f84dafbc10b72b297b3962dc257d0293d3697a9034ffbf707924193d6991f6910f04bcbbd9133598d6e07068079b6897d0a0b551e64e7fbc4b649f5b1954674173acbb6cf3b55ba3911d62f9ae4a3f74ed8d87f486e9b2a24ad714874da943ddbbe643efed7d5c923aec893214504913eec5b6393fbb18a2d5f3b3422b190058e81661605280c71875083d36e886ba7416021de2221ef42373a7965112054d09e930ac7ee43c974714e7b9c7b378e41f87d075601d81c560d1c7958f4576d85f012450ceba8facff60c500cb92f68652bfa272b9628cf827c05d9a057499712182ed8d59e50969104e2b99ce13868027bb2e95b8c5e125060fb6dc99c6b9064bfb1d5813edcc3707c378e4940bcfb6f8af314cf50f0425e66a1cac7374434e08527f1ccc89653f8d5aa32e73a90e76b4b2effc34332e7e889bc02fd9d609994c0206c052c884ccd9985b81d8c3703d21287b1fe14a131b341cdfab42b2513c8d6098dca28e95aff82854fef44c86da353e9648afd12430efbd6f8a871f597d33ff6cadbfa4fae3f35c3eb4b5b22d17dc757f51a034e279ff10402b15b5387086c47c29977a68ae9664b58e700e8b84da3ad925628215201bd2ed66759802ec98cbd49fa1f45ce3f7c9946f075df28dd95ff48e47941d26cadd78b34d41e71261e36cd885302e3d14fc8c527925a8393a7087576908bfcb3d9f7b98814379bc2b87c42f34975c560acee222f48f514c2d6c79ed43050ca48c0a132aa5d0c2fab7b156e726fd3dd4b5111442bc38d87c33c05e6fa5fcab2214311aebbdd2be55d6f12b29010e4d46e231779d766f3c58b48acf6ac5dab563f77bd3400a0a772ea5b781f96a818053b4b7a0836d5ac2f33b9bb4a546305d6b9f7abe6e71dae2f94af6e2e9683da260bdb55b001da97301fe1697df6faa158cdf60b9f11abd108d2f054019143b0ace3b29a782eb68e0de59b8bc519139f7a6bc9e5cb656a16db32619d59a10350959af3f1ab0b49e9970dfea04522a29815a18ad20b2d0c842d9aa80033e28b343b85c76b259da84865d0e2c73dfec612bd01046089eb3c6a5b559fe0c6c20f1d9b9505b5a443cedc33c80e88cbb9801485f0340a60dfd229b995dcac9361bb16fb964d2677b9814922f35da88a6a5f7f79c3c850774bb5f853d2a587596f1f125569c844fe834925c39da768b58aa7f6a6a64627468b9ae7f934147af2bf89835156b36a7c86d26efaa294ce11713246fc78fbaa6bba09dbac46ca469d21eb6a567cd026eecd682ba3c5e311a21aaceae9411ccfc1216c72a4afc776ac403edf186e7b2a98c4b1b103f403e77f7ebeeb32c265a3ec4e3ca9da73b0cf026951f9964a7b1ac8b1dc501e1e621b00b0406e1a158f9fa5f533bd2d722a43ecee22d06e64b190d829b262ec1e87671e62190e54dfc76dab66023b6a0bbb77f2e5cc4a9b9a14c65f381eafc6e993981ae64a5440d6145c3153bb362b221dcd8adb0572cf64939abdef9088ecc8ff5d71b32a96c3fd4886810a9a0c5b63202cd771a4c2a0a2a388ab2dd0f9a25daf60c55c0d67ddd1256074fd562d6c9cfe9b606eda055032de5652946fa045af62744915d86c982be14e4c59e8eb4e605c453cf8ab790c4bfb545d9e22fb9e6824adb4477aa3bb6ce4ed12187e44f039109b144901f525d162e7dba7e0b13ea0604a550fe00b7fdaafe109b40b71afe374828de7ae2cfebd36753b3077c24feaab911f80fc3e35ac2d0d525523b1a8e849e074723e95682ecc26b806175918dae80376856dc961a22bbeed016b312b14487b4ac9cae82d41c31738f88c324d5913dd41473ae5b6428f1ce54e799237c029abc085ea40f8b1cb1af1ff5b8b218c29106611bb5d1596a5e19a8d6b5929d29075d9c40ac3e2505bc8140629d1626a2ee22027a9c71d7e340f5e99d2d66d3efed74def855bcc0147a30edbf0d7bd257d5b44bae984b43b7ab685791ad18cafc90b46768aeb6a3ddddf109bb118ed49e0851b344fd26f520881c91ca61f1888f45a9bc726b75d4bb5814d666b59ee36d9292c61b50bd854ee91ac99881e44f71a2197b6ca7d66280de36cb8671503e093d33c0bfbf4160f7ef55367b04d856a2b6fde3b53da59bb0249e1683cbf45a8fe8f51ed39a0828ddc3ad32b24340094d1b3c1fe4bd00f64d5942a5dfafca4ba040e7a6b591fab12c826fbc0abf191a27e727569bbe8c2aa8b50a92e8259d9d4609b821bd525fb9bf6f26866d6296e0dbdd9ce109ae75a69f8d964f9895331aea174eed6f7a446d370cb22a9c635687dd26391c8d966706b79e7bd5fae33be177c28b31d995b2837d7dc3301f8b58931853364d989292b143b34613d80dd5540431554204a4715c6089d120a2beac9243ac98fd9cca43058243cecda59941c28068a2de3cdc093f5e90806b1384f831c0ed010c454fcd75e558504b52d2e5782508836a4166da44369ad5429492e82b13389130b5ba111742193b7d276488ab7cff6b81800edc8ca3a8e1a8a874233800f7b621a164bb25a9c1d04470fd0d78f16a434d2583c7d3ba65bf2d81c0572b9ef6ebaacec687c9f6b2a8400392be22dbb12fffb601aa5c42bf237a8391e62433fc1e194625ac5816a1788e59e6e8c6a7cc59cca090c7a724f6f6fa56aa0ef575e7a5a2145cd7ba44de942298d42bc597f02a80dc8d9036d76588de12ed655b3ffcbbb17a01457dc7bcb905c3209b1bea7b8145d10d1dcec53ddfdeab0c61c710105143169444d2c6a7876c6ef46fe1cacca27d263ade1bdabcc9caa1d9d0704516229c7170db036fb279b35fca3c60fe4fcb2119fe00affde437f2e2d3c7a1ce82bc7de7b4f16d06456d1195639460addb44f2defd8a2e0f0f675839836113c10baf655c5770849a504ab1d2500b389df933172965f9ebdb236dc3c204c2357477c588e0017caa0cdc18d9ea17b5d2234935ca2473fe082f1d64b16295b8d1e4c0a32dfd2f7b1dc7e27ae9a47ce38ab38b700b14c3bf67d96e666629df85fa35ecbe4bdb6d6345a63e94f414c0f6cea8b3ee364b1da1177af7e8a7afe9ea5ca37b046f893c2fed6cd67968e929025d6b3d4799c2c6d0e21958688b9ce11e375880b6cf5997b3dae6f4001a1e55636d90bdc4ff2a8fe7f4034244e2ea222d374b5d6bbfebf300000000000000000000000000000000000000000000070d131923272c35", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "fe1a8f83b9fe650bb49af1134a45a69c6e7033f0ce6f2a5ecee58c44a4ee2f185a76942fec15275b1fda1834b7aa819dbd3390fafe8beb84b4e50ceff1a0b421e6c1db38d9cb9c5f28ff3ee07d6499349dd343a18f658a26e944cab28a4bbf8513cf9239de7a88e81c8e761ef9337666799c76ac8b19c1621195edeccff93520e95e695dc24bef2fd8f580abf0581b7002697a0fb70456df952a1c7b08313b43d2a06350b090ac2ca067c606350c5bc003c0d21946d8f4cc1ee39aeda74babd62b5a17925353c938e2c9511d0aecd272c569cebde15fe569e234b519efecb3c099dae0b7024322cefc1feceb4f8f932590f87f91c66d8264e5579a1ef13c6c68e28d5c8c655eefccf3713ab03ad859a4e9cebc0c444627b36d1f108347b788108176b8330a8708ab6dd15cd772360d7a276ddc76a9f4e4cb951b9134f939e6e3bf8cf7b8e9499c8105e89ea0ac70ec1510dd531f2550c370d23b94f6c0614ef6d8e8803472e36aad1f6c9eb8bfda2cf97b0b2e972c364e47beffed00bff4ad73b4facb1c87fb713f53735a88d15c8aa5b001e183bb19a353b3689732ad92eb3a17374d60773b0c8ce0369d4ee4465167d33bbed77334b73307889731dc7221c36a79f102515f7038e68f2091325b96d053f04c0cfbb111aa144206ffbba23af79448e35fb512d079db93c2a7d8f55e4cce3724c71f010a2fb67a05a8894eaab3a6cfb44df34567dceb91c719bce882eeb740ccb21cef38129feb2b55009056924e59328f3f549b6e5463607ddb028c4c83fc1d6ff892c4e73a645d4a59652951004c0a3bd07c41c40c5e601db5878c251dfc6c53d82f271ace6bea740db82363298d26f4c2cbd246bde6bd407ce180ab0b98b6c7b55fcbb3abf22060b8a823d180489c66b14931d025f04a7e83acf6ac64d483be28728da76f4bf603b07190617ff990f3fb68abd5769c94ac02c26dc508b2f8cbca1d16a0ccd784b5e69901d7258ab7cc210489cf9ee90e457efbabb7323a0d0e54964a782316e1889b827dc6f35e8a88aabfecf322af7f1ec91b1f704f54f428c799bd4293794f7cb0c6f17dfd88fdf21fe61e8401ca794b9c89e04609527aff6f9e1d07cef0ad818cfa9dd5cd31eea42f51dd03b7feb193be72d1134d9f5bc3ee50a626ec0df9abf455d73bd1807da899e6431e52676ebebf21d3d5b9a2285f450c342da09a1d47e0c54bb852f5af226cd9f2fbb4e737b249563d40930efbd0464af772b1da37a9e00b800e5cea60054b3e31ad41f4958b7f30f8b3fbbaded59e09ffa778fa26043300dd853053e5bf3822b54cadb455529455b8f49f0db9e9273ed58f60e1abf5110a0de30604ff96b7ca358577385d8b3a3ee6b0b4139e4f78e1aecbda99ea2eb0bb951d5d9a4100067e802401cdf519fef6576a39575b8c34eab78dcf34e07198a624c57ffa46dbd1b7f620bb490133ce52dca7e9c16cfb55458a579aae8d9a3f1748af99298070c5a7df71c287ddaa8e7e239eb9ef432c38842eedb6b0edc1e40fcf47ae62ecbbb776b9755da9022047facf43a6ec5224956c594075a2bc432833dcd79dc8a4f54df3a865e0fcd38362be7f86f5c6bf9b91b792b1d01f9b7ed2bb091fece54714e1326a374cc8c7343c36917294d3065cd000940262d8de220dd7e17e5e1c3038633413a7d3cfbbce5f7378de7c7d116876d5cf167ea9c7ddd9dcb2130b1834a3ed85cb7149e22f3888feea8a8c3ac684f97202f6cd7e8d7e221b8d683eb844f05ee81217c9dc8d87bbebcc3547c99fc0bbd999cb2d6867a8ec0fb9a843cc1a1b61ceb5d72012d142f83becf07f9ba797e182d153ce45be19f575571dfb83174c8d6f7b6240597914826dea64d2f55a377dfa16eb1b4b791273e5a72430c3dcec75dbd133f9a8c83e99563c081105b672fdc7556dc305e565b5b3b641dcf891bcffc7d06058dca024afce896d5cc998898fbee6de745cebe7c3a93bb0eddabd464d9630b497da5eaa5d3a7b73ae99fbcb537e3ba5df48728194fa1beca635338e9d192b022c02286f9cc2c397ce725526c725d3d39b92a9f75eecf063d101efed4f88629d32a52f409ff0d107be14647c7baae7617bfa3e863b1070a46489a9c937959da31303eec0cc9f9886317135b1909e8a5ea8dbc6470f1a825252e1755fe86637b69e12ad51a8370cda03b467a2b884f3f4249649ecb367932a6b742175a0a7eada6ff515ea1c3755eafd179c5523d15277cd9cacfccdf061479e822d8a94a4f96c40c0b670fc44360f24c8de2fea9b9f0c2675e4b70bd5a2d672900c7d4c74d29a098d721b6afbb7db5bd2fc8a04428f55eb534793a8f699ae3bcf71aa50d1e47c8f4a0f0a037d7ef8c00787beb60b1ee317c341be56ead6ca0d6fb3c9cf14fe09e7be07b07d3260bedb3da1310baee6360a441a20a0a15b1ec2a5b524c7e4769f1bf486ea4df47ebe38b3e8043dfe16391190ec35f81fb0e054b5fa20abde7291543628505118f8c02d9adedc299126ee2406ac34239ac0100fdab88157a9e04759e2cc2aa702c0aef5d18f434d8df819f30a624541c5220ab97cc74a9afd631ba06401d4320874cae732b487c2147089f747eb4ec3c59955dc75d51a0aaa0599c31cfb5925febb8d8e344368bc3467546b1d4ec907ed0472113df4defaabe27d673b598333b289ec95d367e5786291e738ed28d24a423f2ec4f06dc73abb31efe6d69f9b8de48b5c83e825924f0d917bcfd23c5d9525636d07cebdc4171cb7d96032d29efa5f87d9660729dc8df2fa884de6fb2551949e8dcc3c875671050ea58830940accff755ea882a9e0d2d9518a2859cee493c18045f928b18374858c3510e1dec8703942371bc109e2243b817e3921bb3adc3dbdb3b5f14c9686a33b40bb55e030937ee063736c79eaa597f48273da024ab513b2dfbc932c5ab5e71b86ff622adbfbb1a5aa17d1c7182eb862e05cb6d5dde9c90f5ce299b936cbf0e7f8bcf62529859f6d20862dc17172c18fe1846845d585363c444bdfd0e5a0ec340c29159883b9d57682c4ea513d8ae27a3d0cb957925db06b1459a80207ea20c80032ae673b01ce67d77bdb9cfa259d42ef82d232d3b61e04965a77a889770f2829335fe0ae0816d699d745dd9d1e1b58fdd6ce71ff6122dd3e7bf0596f7db237370807b1302b638a71b59faa9fb034ea20e989645313873534d2876545a7cebc590c4fb26cd4f0cd243eb3f5261e86718dcae76fbc9c17d7d079ce1cbbf892284d55356b7aeed19fc7b81bab9d8964363b58e6601e1858de0bd0a700819c5ed73ad80b9d7b1c14bebe4cc752e7863d55b9ed39fa436bd71dffca05afd3c7032a9a68e0cab886ad170078575d7932746eaff484e7a9511466757e20e9f2a08facd704769763d45c1178188a95ba05aab34d61d0ed922204118e4faf07f382539569809e51a08ad630739fa5abe62523a31c18a36ed53fbc3df2b26bfd011aef0755bde3b65650aec8a317c5f3dfc172b702fcb00803941dede28ff49aa9bd30cf30c4f650adc18714dcac4d58a4aa2f5fd9ff3b2650aa0a08632bc82a7fe48e0945442cf4b93a5650a38df8b3c5dc2bdbb9eba9264a53050a4cee1b3eca95cfa7b1506433d7385a23e5e8e2e689366c1da251b118e637727513", - "tests": [ - { - "tcId": 75, - "comment": "expand_s requires 2093 SHAKE bytes", - "msg": "48656c6c6f20776f726c64", - "sig": "265aae89fa2cfeb21e84788459a8586933f07931ef592553472644c3bc7abe42011a6dbf795eb701062aa0bba1455e515a9828bfc3f2b88a499834b5d31fb29cb4ecc47c8df5c4233350d47d179ecaa58c51b86f07f5c1510035bb775d9354efd82f8b09af2d468ee6541bcc2a02226938dd66d1a9e978a3c7b918869bcb773b4064f7f68f45e0dd03aaf70e683b2b66049edfbbaf28db28fa9292188af427f84c6dccd4b4500b327df68f414d5efd6703c47082d9e7536edfa84625e37e9b4867ca47abcf295d503091881e11104878239cf8cdc483095f807010135f118f9d65cdded047da0b8129259d13a0b4557f496a50e73918080a27780db7d9a917cafe29f5209f130dda3d437ba64b94b2274c910b015eae1c7233d714e133c52f532cbb655e96cd1249bbe0ee653d173f53b2d324069709cfed742df36aaf1e506e8f18342aa44919847db337f9894caca2e5fd10778174b70f4b0ffb065e64deeec3ed81922a5be4a3650117201ce8006a0b1fe0c2456af9a6ed7d8607cd62c94d720a6db097e71c088678f0606347156ddcee6ceaad315ef1142a5dba6bd7c4d8fa5df966d9090acbac29241371b8363b06202200674b36f26fb4513f166d2e1a98bb34185a02b8b6d9d308037223b02c33f1cf857bb3b6913940c45f0cbcca559dff27b0764753fbe1eef65185e2f34c43a8ba0054d5bca8d0b4c700f16ad46b70c1bf8395f1b05703177de687b075f450896c76ae791b80af8c5a9431cc773ba44766d98409b49b661086973a29c88c33683995dd9f8c78ff6542a4d0781a4a4888f0d8b7d8868b67b3e18e1ff1377f98b8dc222c256adab2129fddfe26c5644cd31e930a9c50b560ff75206ba8109727e86928553b18f4551e53d29d9f609d90cf1d821158aaf39a7f048af4990044e992805dcf63cfe24060bd7bf02cd16e6f6dba2a1fe450aec48a22b158d0f2555b145f5e6c461d23f09171c2acb50f79e9aa8e1d7702bddd692e6efa50d80fb2fbbb3987cb54e104d4d85f7e2d5443f90b0e32f5d4277426d3334cc6e74429cad1d6cbd92ac966b23c1825277cecccb907f914bdf4ef13ac20a8e258d8d2d773305bdf003d44bcf521a33e4800c42f936166f8ce57b90e8826318cb89f608c45b52f4fce5e5bcaec34d2a636b355200485ccf454ae8950df338430d6a6a047dc4db120e2df546fca45cd07b2c0b760a1bc6decd35d408fd0683949203ef6ea94235d36dd6ecd7425dffdf78af79f6e90209614bfedf85c2464e560d1795eb6925ed710886ee75cf21e8de42145cbb18a11a5288da030844c00307cc8651989c9bf00a1244b4704f87aee99f247195d34a031df660b4fd3ff465eb102b188b87511403bd030c200366641dcea5e00c1bedafa0bcb0f84588fd08a6450a69f7cfb405a20f1b8854fe5660ada56477a4809d8d3fbf1a410cac898f01d3e51912c37f240e24a4215fd85d737c13acc40add09b615c1bbc9408e51a4741a659cefca43dccf08e36c2ed5ee8dd6b71a3a59d91321231a985a9bfc3cd742a51e07f0e0d3ebf9d3b9e2ea3314effb3a35b342161c373098b0dbd10c14cc54f745370629fa299584a3df3a06ce99c5db7637dd28facc5ab0890b468195217081b85cb908b89192684cf1f1ab7ef198c81a6afaf02b6c062149e1781e1141584761d9a13320beac6e71347e5a8ca4ca9b6d9908e6e0e10e4a0412d173bc865dea5aabd163004f55b7606bc79f02925a317b119010b4d8d9b9b26fe024f059b16827c2164a598dda2aac0de157536c25916e6db8a58037f79dbd5c391e2301d918968ac3c1e353e9c64c2c105b08aa916326b0b581e6a67336315f5fb74758cb963b2e91c044d25823de7483016e2e19e3aaba570048e03de3f95c9bcfaccf993b4b4a31556c421efd7071a52c227da3638cd82aa83dc3856898f05f15239276e371efb0f4942e2bad9daea0d7054f1a0d8560af5dd22f53aad4e2ead48270f2b36c39f3d07e594636771dddabdb159ee80b67f7018ee8a21a1a6bb08c45350620a37b868e89d45050b873b759bd685aaeb5b0783948db22229841ac293ca051c5b50bdf512b610f61a8eba2b539e2763744ae4746fcebe6586ff6812d7f51ee3f09ffb5004d9660b4472ffacfa3f1d42dc742586197390f2135249b1141b97a2ff35294a80c84661c9ae4041e56141eb4d107a5b318e9c70d29f1c58afc804fbb2fcb2f3b48a430710e41bab7ed6ac2cff2cf662421b99cc64d32139c783cf80415fd16d7dd95f9ec27829b1400bae9bf05c20bfbd231347bcd139383abe4e3e27501a463cbe2abf55f470553ae0400cb108b246458c6e0f92fd844fadba692c71fdcaa229652473bbc31d6a2bb03c53a8eaf56a8f67cd40d2d289dac8e87e969703679c5efd4871cbba3c3347975f2fea1ca15ef5f97211049e81785ba7f5e4771f8c90c37df7cc5410c7f7c2a27ece65b84b95c878aeb05dc32155e49f1832c98ed5d5989fd02ca5f97d365a72145f740531d9f5e96ad222be91e5a06feaccbf770f7521b6515a92ebc4c7afcdbf3626271717a4e2d3d1d1e910cf5d622a3e6d8addf722c5c394b4ac98d8ce8fe09a01047433557a57e8b0867d7c1564ef66c2bae1682a1208e8c1bf9c8ef496b47bc3ab9ecf83ab1ab8a7d17193dfca263024edc6fa35ff43bf48290bc5b68aaed8e4d6f1e75cbb76afccf0415a7c0d51694fa9d3559f261309c2136ae6caeb6cc63a0599959a7b5eb6f2286a252310f8d42ab475411e1125263d15f7d7656de96383ea633b45c819c638994c9486803e0113326d49f8cc8e46bbdc2a51cc30125c000dbbedea4f5f40c80c105d5c75e753d1c32726a7da2fdc1553b7744fee3db40d85cdb4fd75a78c92880ad01ff08b0db9c0455e9934187716dd9f84a2120cefd02b0cf4e5158227eb42c597f14124dd0eb17367ae9032c75e60c9f449e168f47040a1569d055b62f1891d07aa6015324afc1d4717597ac989e964738838dcaad6d429bb140af2e29919788d1b2d501e8bba2580b394ef79768f7f6e4335fade9256e0cde60d9423017e5da691f9b129ed90313f9aa98a2c962ac5977605524e344fe9a4a67067847cf4abfcaa9a385ae57bc429f3d333994239eeee8f8de5dcff1ac61bc09e8b83e30908d8c7ea8dd52b62eed574a9ae4e7c0f43f39be8b7f0e4a7902b5eb566d3de159ec84c82847049af537552db4c17528b3fccb8b7fd4802f43fe928809a1c21a409c5e84a748c5bd99a4b1ee161becb33049d97f0c8ccdd16fcd6eef64be1c2216a83b38fad0e625589f99ad85f0ebfff0cf8ce1b6fb1bbbfd086e4e95f44d35cd16e179a3e9f694d256fdbfe9bd78f6bc0663e60080348447728c5f64addf201e8c6fb48ecbbab78800242d30e9794f57c9e4cac4840e337e1e868686f8d6bc7c99f461e78d17160fb8a1e1aa75e6a99f6d95ffc59158794ceb47bdb6e04cde259289414e73bf89bed72787780ce29d0dd94ae51263318fa5176a56ecad36e0b01f461bd2c9f4218b2fda692eeaa640315088d0f2b7b90fe83ddba092e71271734f1d81290cf71f863037d5100cead437e03e2ff8191eb893d44c1e0682d134e174df9fc0d63557e95d612f8f2809de9b91502d98d447889f9dceaf1fd2205e52bd42929875d1b92f039706dd905ca3c19bb2bc6e8975ecac8835c19504b261d23a8847aebb9438b7d32da2b02fd4b20234b8250ad3bea29d2a8607148c7abf5771224280304f32783bc6be2b2813666478380885761a18d555a4b8c9a754f7d5ed799f29364894363f67a5978aca558abf4ca174befc4f4556a76c50a8350dc4778447456215232a24a13b834ccdd045d25a6c8f90be71174a20cf2e6ea6680910e40e20df7650d6788e3b434de0650525adb244b7af313a4c2d0317d7208c41f4583ebdbabb313da9326b4d3361438f804761ee3707f0b0fbea825c132101ee83b86d35daefb0526846394253ab704ceb3d5e554fb93873837a8a8d4693ab9f6d8bbcdef29f74d1fc9d9abff0ab2a8a952f429e3d5a786463c872035458a12d5d97898211df0d98530b19aa71c66f839fbaa6de66d5cc7e6b165441f6f8c1f6f481d184edb13bf6604fd93542e0bd4637d16952984d9721ef303bc6489e9647c571f72b8399ec5805dec0173b987029e7979d64528d80c4d850be708d46cef2aa5b4dbd007065ddbc3f961a071524b022ebfae5faf329493026b5445f765f2ae588be831d97fa4b56ed7ebedaf035e3ffbd7c1c55ab3b15c42b750e0e59f13b37bd18ca35bfaff8d00474bc90c652791672661f562408ba24f931ad110b09464f115c99775852ed9fc5d0091336f62e785e523b6f5cf02aa242b9fa3908a66106f03eb05656a8380ce25cfdb2ba474f1e7d1ead68fc76399a3368cdeb6a5504fa7440ba3db498ef656a979eb7bf24600aece7c5a57d7abe6ea5a08eee52eeca332b05ce14f6f30a69234e2b07528bceddfa1b5d2a6290fea2bb60c7f5eb1190d664c42354cf6c4978dafaad55628dc39fa2c9fc2be5757479a987d21bc52e123d8e47697dedc25592cb2e38bb91495b61167c86a575aafe384b0269b51550e8aceaf6cf14f3320ec3c284b80ee780d9f13330149ca93f54bfc9cc7dd5bd0c893297089149d1d54b99a42bdecf63c694df5d820f62cd9f0ef0598974e915e32c1962cae675b027a6e6da58ae45f794140070faa21f415225d040a565e938449babb0e3981ff496dca9accb645ccc5be3cb4174af5cce2e07f9746720d8d60cd7451e47736056013e382cca40607986253dc7411e870e22a52abbe77b2ce40a00a2844a22c7fa215df78d5be1c5a0b739773054551953430e22b7d57e0cc8129232a3fded794a7f56dc4e006df5be2086e6630a97edf28777fea637c457364a5e41eb4ccfca6753345ccb6b474c88b38d781bc2ac013d844d963626a70811f737e44cd490d8a172dfd49ee54534446e49ebfcee282182951be4b05c80df24d1684e0b87f051930e4279fd3f5fa66beb93d3e63658126a56b25fbae0dada59fd4f8b06b897816f73ffea107f2466642caf36e8138d1146e0d9ff8387595e870d98195eaaa80398f0815c4642631e10f283a9f27ae34f9eaab6373da9d7134807d0c34ea5b40547a4a463d346608dad6d68487fef000b773fbd355a1cc592c572a4e5a978dab85ea642954dcc008779bd1b90ad279944453cb9f6014ddca80d19e72dd954a0daee001eb6eeaf814b56a5540245394c9f4ffee402cfcbcea500e7867d0d2636659c6e95d45db2d2ec3012a2fb0e1d3a1658323f06ab833e58c599ea851c9ddbe96455c9e6700f5fe622e998954bd183caa1077b276476f7a6e4feccb371e0056b8c33286e3bde62a2f363630fdfeb46d6dfdae24c7282abe8a049bfc66fc074802220ee6d7785ff07c971dc46148eea9116155a4e2eeafb5d2dbfe8c3e31a2a9c4a58b901e79da754473cb5eced2e0d3c9061a949423e523c9200dd7a8ac5a2309449150456d3606c56c5a93ea33124b7032bf5575db47887cd0be447a09ea37aca6dfb348324d93e15b3a4b72545c046b21db863727acc506cd13c8eccb23a66dc38ec6e2a8880965683210c44d52c62ae01e303038f251338f1a65d8fcc48113d1d23fc994b8557afb8f60acec4113e3a9320389078b153472f7947d796acc22cb916d32afded3dee8344f5c5d514d7536433cf554f735a510e2c2da270337530efa42e86e5d024cfa4252b9cffa6931a9ae6c5e9ac9c955ca398814d6660275f33caa59db1dbe040b26c4ae73182181683524dfae471cc912c2d5fd0044ca4cbe83c636444e0e692c2c53aa1222e4b82d44196bece980dfeb2cf0f0b0c7d5cfdaedeab1a9f7cb45222aa2814293f9736f3ae5a8b657b635f25f6005606fc4f622618d064f623c7caef9f1433e6af8e5dc0d17acbfd483cf416b00d9eacfd0363a9179da0aeddb1c45b2a41690cf6065f2ec56460c1678f7f90af7237b32a60eaac338a0418fe3d5b5f2da5543bc1d42d838f7d5ed75a93d60e0e2b03a2cf9cdee143af5ec70fe2bebbb29580c54719a27dd898a7d3b867b4770be4a06580a4f54ed6242cda2bf533545da0bc8e4f7586bcc80368aa3877a92cdc6b72ff335ed27c33bfce7e4b5df96e5cec7bc6e9c556a5ed4e02a97e31b428f33794ca8063159ca837c90cecd011d6ec62d306e292f246a783398c0d437f74ce9e6739d1db52197dceadfe8ba8d554db809c230f7a36f79d8a724153b4d426df8eb70452d54abdc2010e2dd5a2a6d1e3e1bfee3d2ab485d3c33e9b3559b1e8d7d41c7dbf1eccbd9211895fab69ec3f9a50b51ee48fd56e756caf1a986ebcdb73f4b0da97d25aa3f9223336a920881353950396034207da637dc2e385354b1b7c1133441589599b5f05c6494b8cde920445072a7b8d9dae8f55a8c8e9db2b6bd07091215556f8c2b354258596e72afcaf14b516d94ce00000000000000000000000000000000060e141e252c363b", - "result": "valid", - "flags": [ - "ValidSignature", - "ManySteps" - ] - } - ] - }, - { - "type": "MlDsaVerify", - "publicKey": "d089e21da77878ddec2ce54dde2e49053179cb91a545559b41ddadee3f7fe633ed7dfcaa29e3af8ba599e60e320eb73f87afd1cda3b16d275198d0852aa3d376bb591511d5ea2cdb4121a9b8fd8a60270c3a86dbc2eb497f6f8fa027ed71eebf737e910717de64f3efb98a1adf3eb2229c159970a9e7fd1f2942c3d66a271db982006a4a24a7dbe2aa3136a4720703da40223592e07d3e9f59bb6340a99bc42a8524077e8fd60fe9b84f6c5c93816fae689ae894404e0bf921bda2a384e98f0d8891e90895e06fc42b68e2a6a5a97f271c833d6ddc873ea2dc84d17d3ebca671c4cb67cc44ca57f00d67acb22e28557c141f777de4b5e2d443a931165b67d716d1dc26f4a0627e9b981057f03bb1def267e21d91ad52a90c4869af8dc8e0a30bda37d273ed008ecdbb9079696fe2f3b7f468d2edc32491a8c86208046ba956b6a0016b381d1e61173bb061479e5cc163b7a0b7c5d616abc02a08e522982f9aec3dd73d8e1baf39404981445bbb01782d6cd1faf9cfca3d186a0d044e761f2973af2cecfcf1e936ad60f9b167b10cdc11ab0fa642f384e49b38ed3da9044b324f582a753aeeb741b2bb9fd65b8f8ffc45a7829668d581b0c6f037774375ebf98a1d33ed252f7ac9d9ee9b180b69445051b42b3d95d33145011ae1a1f84f563d54f5a5a11e283584d9a92a5d2e93c364f42b70985ccf7d98528d548e55455b48dd280a2befb8bd88ec83e5e6717c30a207b95aa1c202cf81212980bcd5b264eef0d2462dac2d095f785723ae5b1babb3ea9e57790e74242dd4cf5c8ed26d1b0665230dea9f5c8efad2183099de6ec72298649b7427f15d2099ce5dff6da0af5a25cf82e5f4f6ef51588321fe0f76d84bd57a08f7ad2c75c3e705f396fb87660c9c574a7d37fab9f0aafa26cd0fe2af38ab06ce2bef5cf129c88776de5f4cc87988d3e6595f6f7719335edd0b49f68813a045a0aff528a15d0ed4b4a3e88ca2eb3fb369d027bee36e60dc2bd36ae6a53c82aadf5bcd940e2394c40e5baf223f4064634fa5193ac5e35d8da625f111442196002db012ad2a7b7712e99ea9fef5ca68651e8836d85a0a3b9739839d3d0b2cd80fdf45e4efbb04e5ca9355bf27033571ac29d0e9c889b8051108534d3bccb9e209384b6822a0dca559e45e2b92531e4d9fc49aef2fd691f95482c645a950abc9d5f18b912bcca1f0e6bcacca0d38f5aaeaf3c42aa1c27e2ef9c260794b0ff7948bba27c4a24cc28fd491c5fad2c86b6aa5133bb66dbd2a085e093c0a8b9e837446ef7c6800671273cb450824a3dcec59b11a1bcb384081350fb415a1eb2ac73969457ee5326d352c5045aca29d71195ef348b21d639a4bf7231b021241d991ecf980c1fbe3a25a9c80d994849325cac842204b2720743867d6fb5aef1b22891bd34850eac5980bd016ad980c6e4f4769151d394378460b38b13ec37deb3537b86642c994b0cb7e6126d92cef0533772aa0c6cb52048dcb558390de246fa0219c888150c702b40c0c3ed29e673d6da962565184b2507b09f8ed454bacad3a9718e35ac3b5ed8459e182dbb755cf10706700b2be5a14dc937bc1a825802766310fefd7d587b5c5ad5cda35711895592c2f4aadaaa2a61c897dc2f97682615459da573dc5425a92aaa2a2a405112928ca951f569ca06ac3e05dede21d46421c2115181622191996839d225fc82773701ed5da6d1b3b1a8eff95d1adeefcb28cb18ddff103cb8e4843b1a675096a013fd24591ba78dad88a419b2049819ecc3d573688605a69a46daff074b2f2f2530995863a488196adb3acdf9adba2e90ad78504641e14326f5d5cf2b2ba6ad9442bb0f40b61621b380617a57a1e38d416ebc5aff883616c8dde832cf5e1176da30d83f78c88c67dc7895742f8eddccc73d0e6821525f24df143448788b7482684b4adb8c6e1b22445dfe643d35cc1994db9647cf06ea618c67a6f18cd264943f8903187ac928a292c850bdbd33b01c63aa0d540aa281896610f4b486f09ddc952d6ec4f552bc876d0372cd285510989930a7df3b3cad563fa46ebb0eda045ef49eddee230d8a51739763aad04e0f08c818e1e780e31309da2b0f5b838960408b15722626f775b9e2535cbcbf7c112b65059ddee5ff8ec183353777ef0decd0a04aa91f45d8f2852002819c4f2b657a641d2a7101d241ff7b822ffe48fc2086a441b5cf45ce10850dc214d7abfb53cf889a839534e978f70412deb7ad4c731b148c3efd8a22f5a10376d8b6efc63c762c79be8ac6d2d72052a8833470d53701ec58c78b8cff39e74d289c4ddd0ed0c772a9de2afbb0c92c542612a2cfda2e2c0564b291ab1459ed83ecc88124958fdf35ef80e71f2ad2343df41b85c7867b66f3558c378c202cd732236bcaaf3d7a735c547585d131675d92263b1e65c10bf4d0e26cca180240ef73bd0c30991e1851fc7c7c2c28b913cfae037d9e115d0a6d8afdb6a9d5062bfdade718879c49e400f43aefa4a5ca9e0aaed314d81d733a33c3821ce4e549069171f84fe99d78d8aae0152d9356a90c98aa9a9c9122b294c3839d5c2163165d54a43d0c8d2959c672ab68542ca41f7d1e6f0aadb58d3bdcf453ab6767fb1a3f3b8b486bcee5e5dab42f5e3384971b722cc34ca4a50eafffb8fef76d7b58eab48a6d4b634e0e7f14e5c699bb375df21b36352b0f317e687c60d5907b9d4de41904d7319e6840a2974991fab6fc357441db1d4d9276ebbc36e2ef2f9b4b26f2aabc9bce3974c03bd5b5c358b448d6a093a6384ed1373a47fa66803bfa0c547cfa0a5c749cfbaf0fc9a54b71185ad7f5de5b62176a90fbc04c355389f3439a66cb8dab2c87d209fd16e80df3c785311b7f1c513e2745a3a906b69174f9c2c3bc7ac226c223776374180f1259bef754a71aa268f8032899b0de650cc9f2119c82ad104493f253b679c97bfbd9df3ac95e180d0a9265e6fe01a23f842b8da6b6818474c8ceb5ea12e4aaafd71249a189a1265903ef5361e4ab6ec489f7d69982304140fe568348eecf3054d5ffbda88e552309a7057c7c019de9ad5e2146d172d05d4c21f53a630ce82ca3e83f1e0fdce5447e9415c282141b9e333dc2f3ed00440fee0a0239219e0cf5de698986dcde2ba0ee495192f18de1b173a98f6ecaab7db07a5a1d1ce696370b8612276368218e29a1094d3a8038cf83941b2008d498cc10c5ebc38b173c777e48c3fd760a4c783f1cf77101f0e5c24673f6925b08a72b4885239613c95014254b44e5e7f07dd545a0a57da00342c4f755ba693d5357f2fa68c7d7ebd1b9ab9ebcc00692f473f57893b6de6c0e03c9180a1f967d4f380246b9fda86309bad2937a23603456a34fe0626e6e76e3f42a92496455a6b7515e021bc5ce82a769cb1ad8de4d20f62f23ad87df89f5f9c9161bbfbe6e00cd85ff6d5c281f975f0c35c49bdda6c811fb30530c0c8a7edbaf006ee46c31974dff8e237004e0c91bd1ad7b279fb3e064d5bd5590018d15199afda40b8b79caeede51b0e53d75480198b3e56547e862087aa8a6b41b058947212ec58f71712d426b826fee0ea4ab7718e787937bdb13e2bf88d7dc3853ac335dca467cc18adcd89381054ffca645632ebae5d1f5d1523dc33f2a32fa144612fcffe6daad6e0cffc", - "tests": [ - { - "tcId": 76, - "comment": "power_2_round returns a remainder of -4095", - "msg": "48656c6c6f20776f726c64", - "sig": "86e08da9ff87d24e9114dd3c0533a3454d408dbffbfdc209dbd8da630cc47780d65e3e135d7559f6d5cd6915c2483c710dc4b138b96f478299c0a09edf45adb89dcb7ed226eed91fb819c3c7bf3bdd66a2ee539b4ea7e39f8c0505334ee702a2a59f5210c53e52684fc6c4f73b4845cb12a42eef2229bf5462319bbf8b9e3decc2be4da0c38db6b0da53a2050e2718291f981af923a4b62d09445564c70fc78db12146f0e8bf39c5ec1abd592ef8712d4362c59808d3e2cb9e591e04c553b4891917a0e4916998d90fa4e3f7d8456e7dfe29f2536e5d94b08f2b18c4f12d9318b98c1b9794e4c7eff03ba8ea86d177cdb07695eb1001ac0f91dc4be4621a39f13e1225acaa44adaa1f05fad415c96e5426a87a3d7768893d9be95ad48a1430109550ebdbc3098923a8a8d722718a7c4949f24d50c7ffa2dde0e6de32e4e6d781ab4095b6fb61833bd49a86d53ee07c0a559b43cbb96e1642a4aa9239dadf3cb43751091de6203bb08e81c4500b6ed29eccbcded68a01474dcc49913b5afc67b338f204fac8d034c07684f72765fb50f329ee88bacdec68080b9a2c8dd43a260f5fa3de09e610a97eb6b3ebd6cd5894c0c640bd166f293635792a61a704176a5a8515f2c19af27e9da7aca58fdd1dfafa2c5525312c3d559a068ab0cd744d32d00ea71297bc090f195c29295af1eae01db47cf0af1a517e1fb7fa35a1467c922f5b11a3d6dea2c4e9726b3eaf433eb2249b8d6825fb7e566514b1cc8385d39b3ec5d2b65f90ca22a1540754cff09892ed347b2d8df1de462fb7ea1eba3f34c7a8f9f7bd98a63f89fd921dec2a71ad17f2c881fc6b3b7d8c41e73a1a2bad7035c3919caf05f93723110d238a64bf07e21aa911a204bd0c38d6d35e586ef11490e9727b790403fec8650dc31e17c404ad82037dc481669c348aa70c337317b938e4af7c1bccc72d9418db626898563f096c97110d3dc0dbfe5e4c192733a0083ff6089c0ab8dbf205b989688103bd38de51d44d6848c052052fc2505d827701ffff5d959774a43b8cbcaa0bd2c0d504ffc5e334642e904db51f62556c31d771eb7697e2adeb1e4522ebce565b0dbc869731a0ac8a534c4f01405e02d53a3db7719f2c5b23b61ddf8733493e371f05ad4f8d2fa525db672fe818590431a8a4bb7ec13679c66f9945bc82e7569028c3f4913586eed33d70194c9eaa6b6e4b87c494ec210990e941ca0ce54220436d2abc2683ab74c605b907f4543e37c46c1533e8b98d184de5cf6c34d6206d5bc48de553b9b81c93418f9e700be848364156a940249deb828614a09bdf5ae72d800b80c60d2acd6e938211252210a1628b59e0aa08402d406ecd644ef0ffa3fb784e75af8090840b1b6ea88a7849a97316ea7865898c4d78a5d9b279142e09ec8d099a4729d2f1bdbba886dcd03454bb58367ce525a8631ea5c32a9c1cd9ca6da3c98c9854a5dbccb5e44d8357b7b199c2ce5b4a023acc9f5e5be5dc9dc767665ebcd4ed39d6f4379f212d4ebceca69eab226b13ef596512cf5684c3d84698dc58c20f620051e941dd10b985ab4a212af694f35794e75bc3856f1936ba9dc42715cfbddd6c8d078b6e44a20cd75557d3b3ead46ec03cea2ec0acd74bb418e14c2657b23f6ea7b3a75fa39d0ed67a3fef172c818c00415e9823ecea15de3708531443249988c5b7df603040d917a92942fe41ef3017bc90899d93a5f3e2674d3f752c6b2c2dea4a139a31a42b0953cb610d833b731b97362b930a89288d07d576a90db0a72e2eac0091968aed7a8251688314580b8411b16babfefab4546485bad3d756b525376f8c311f53d021cfb30a88d51c4b0d34f50ec01c3d048f51e7865cc2488ecd7db69254b1eac9dde3ab3eb44fe1c07e1c3fcdbced9791ea31d58abb926f9fe2507a8b818939b142effb658eca0859ce3d92cf87b2505f22286c5b538c600de300773daf056a97bb595b2e38a86f985f45c0ff53c95ea6b379a226fd1bffa73affa56b727dda0122c49268ce3e1bf676760fcb5627c117dc72dfc3e1125bfe02b95aaa49f3c4478bfa5fd78d7e53e9f8eaf4988b21dc46192a4de5b6a7fba27d738107876cb34f4c147efef55771c9a20e52e846ff7314ad0da8cec4fd9d558c4c7acf1ff49b80b1339363e59b38ac482ec419dc95298e120e0db2215d4ec6f6df522ad6ee382e363aa92818b61ed6d168b0ce66ff6d70456a0f001b2a239a22951f1da2bac44a2938bbb446236588a375647637000ec9765784043b00b7bcf44014b0a2e030321d59b6605b6ad563c82a7ec7e086247456e88ec3a85ac667995343495aca19562417fbbfc65537fb50c9732859da5f4e22701d3f676816746aa13f6f467472f66e9fd6c0d09eee4c4de139eade0d9a012fa2e6b9ef2c500df8bf218044559af12ec3369b68a00c9c6261ad821b3ccacfd0214ed27641c12a8fd3c9502efcdca235a0fbc84e800b6f591ae9bac2aa56603e1ba2fa74124af0acd616b644c5b4c86a2cb3430cec1c2f7d8bec0ba2d4059cad591d5ef3ea130fc4cbf288effa82e09b460f6de1ee1c589f88ba593d9ad5ed7dfd743e5a00af641eca21ca337988940bf7baded1d4e4abc18f0b7a70033af266098d104aa8ef7270ef9d78b2506d8104aa8b1662fc141c6e24e50aeea5e5e03d4e38f976e941cbdef8c4670d08661f83bffe4339ebd084c217dc39414997c80d020229944a3b7f8398356ad3e4fc1bfe706868e2a8d85349aeaa284a224069014cbb5af01f2ce8aa80507c7ef64df69aa30811ad0340a65756f36027f9cb7e4f818b8c5dc3fa772460d3594ccf50641ece7292ef47fa6ac0bd7bd982f18a11d8e99b0fbd24a79c27f82e13fa7086a316eb1fbd13f3bcc36de33e18d9c7d0b8a174605af75c21b5d3efc0c8d39c91a8e78b44390f00a7098bc38ce9c28859cd5aa27e9b71ccbb6e95b6016aba899e13df66f874d5f43fc2b047b44ba06307fe1935b79e2b7a543de664c6f32a53ad75dea85107bba896dfd9c958a82471abefc35b8ca282bb4b9c45ee5dd21e1dd7e5be533f22b9e0744edd58cfae062043c14e94b9c22931d420ba5c2c6644e3544bdd7d65aa3ade50d9676daa922beb8a93e85597f9a26fa164450ef4a0a73e7b6b1b2502aeb21e02c8e39fc7050b24d267c49ee5893f86884d72cd3748d7ea8c05da759a46eb905c18e4ca3c3a0bbbfb689fc47d528311f9eb5cddf5d240308bdcba66ce37554faf636ef229af3180c3e18eb2aa72ef5b88971eaabf95550d62464ae862f3202bc80361e6848989d96c0dbc34325705da7cfe4bcaaddabd2da11cb1d47ce1555537736b15f73e7c581b8dcbffc9d90023015fa498b5a06cc9a184beccb875576cfe7e642819f30756a33756b585f58cd57e12d08e663127e3e176ace66a58cd271d6da8f9ab3b5c5041e4a6203d11f11aa632a5eb5019402c7ef09f71ab8401093df3b9db9dd814c47ed9e27aedde76a63fecc217dc676dc622535cf87083ec7016fd9ea45a9fcafc28476f232e9d5c7d4422c0377e72e9f2c7ed4b1a4f13ce3f493dc7246f0b2eed6f83919102ce9288e4be835f5303d4cd545e848c75e2fbc235acd6d675b3fc533ec0539a7a9849993da91739a9bf1f346f93623b1cab407abb8f5bb7f3ffbddfb0bac914457237d387634bb260d228add5e520871b22d0314f4709889b791a2cde00abe0185ea3830975fad6c314341ca18e291a4bbb9eeabc046bdf7f498f025bf77ea1bf055af46ba60f2356e3867b67272da09a211aa617c3b7e2a139e85555a6dbd61292ad24fa13d11acdba17cb0865e0aade165201d017b0b3129c84a5f85c99aebc5c7235f72c96ee905c9dbfaa5123daf63162be54378a9097329ac088d1afc619529d4b98b2491f766b0f665a777cd1177d9fce1c54fd076c54aa9ad9af55ef7c1bfd9282a9ff90baacb614e33904be25d76cfbecb79397c63db368981b9cd167856b531ad334a7cad3ca3a2cb16307a41431e4a7cb6c5c4fe0e79ed811445e1bf3d733b89e8c3880da7b456377285d1e750f5bb3291060980cfc97a966494bb849d3659a79dd70d0cd5fd3dadfbce03002b90fa3625db438296c7f5c0ab47f6d704507657d142a45f3ae76e90f49a4199f87afe62ddbb4d41b99be8d96b4360f672e39f0ecf54ce1c3b49218a868ca79dd4c1d4a86eb9b16f9f79722829dfebbecd15bb6c418959f3e7df9371df39e4dd440848cb6db30d1c4294f750bda92bfceae516f0186eeef691cb27ba061abdf20b34a98c7b179c5d1e8af033e9a704fc2fe7e15e63a9adfe6ea50da43cea3de59f6a6510ccbf8ba7750536a94e7dd1d9aa97f98ac40afa9cd58017d337dc66cc6ccc53e2eb982ecb2f3bbc3548fcc3095d3fcadc397692c8aa3355f09eec308365242ba1086681333619282387d33678a8f4aa4e31bb726856cbf87f81f52b5411e2e9e82e8e8b3623567c0a807c3ead822990d578abbf2ba58214de093fcc01c79e1f4ac70770b0c723e0d5959afcb11c2e5858a4525bec2ccdae97af847b0343f030f08f819cc004de932f390f644828d09ca9bd378013672e93062075f25da9d534571e614bf6cf23757a1c92267ed2341876777e2ee989eb66c76afc2fef653ff7a0a7da34f7f0ba60a2322df962ed3467816d6b445deda0995fd8c38b4dfc8fbee3ec827fc299b2e9e618ca37d257782a3c1a80bce4c3e37486b3b33dad9397f97f9bec1ebb6ba29338fc197dabff3b247a9c87125eb79db107d50489ecd762d7c1426eca9631354e1035f8150f9ab515f9d64d72f2df1660df8f25f0fe8d28d3aad966c140e9d0b0d66343de2187e09e61ae0ee4d6ac317c59773a2cc629d569d1e198e3525a689d2b2409c9664b371cd9a4dad722db6931ee0530991b6c3e5d57735e090ebee8ac73c6667224201c79507c897bb21aed6de932b9ea37398ac9efa3df1f71817e4ff07557fd9b440d9c3c0d02e0f1a696411834231ee377578620e879a533b41b7fbdf22b84c353388562cf5734b428e8dcd41c9c177b7d091e2680b4a5f0019e80c125a09c9db837c77d76d1cbb59d59e988410f52c0b68ce3c648d225ceec3e9b1086671ddf51942dbbfc7af4af6f5b26b3cc14ca5f4056238dcbc5a8ea82e7d223fa883df2fc850b0b88e35dd50d3453dee07f2a568d788168b2ad92f0bf6609f97c9fa29804e5ae70e80e0427bf5a23b61ab6d07bd8cb354068654dffae490d969d27cfd5ff526252e674cd1cc73b53f1efe469d9928f63366fe69f4619941cb95244d9a761406c755ba6bc41d89c6902523ff2b6d8c6a3e9dd1b4cd3adb864194f49c35015b80cf9226874532255acc5dfacc797479853d8f5cbc48d3728c732c0afbe3b03dfc5c70bab8bb7f3922a67132c41a67ef24b7260e649d6cc31583a8b1c5c9cfaf035b64a1193ac267830f4c371f9ae2e37cc7f68b866ee3ef4b797ae15ebac4ab5caa56bcddbad10cd4167489704e09957b8629ecfb66e78e0c35a9a880b12ed33733dd76f691db9aacc86b367fd3d16a1d3aa1e674b247d6295189da334b9b8a58384f73173796de843fe69b0945eb7e0f9102911a2c722d6777b3387c303e14bd5f5308a940d7e359facaeca1dc28b2b12e9c629879a710718b7893215350251ef8a4aa46e87dd909f77e8a7993d40ee529bbc638d839a70c8c5f75cd474a85b75aa9166b86cbb39b8f8818e3c1edb773668352c1d48c8b7017fb8a26f06af3ed736345306394e0e6ba1a833e2ed8c374926e6c00a127765e3024a3bd061d22216bf038a76e47a79bdeb5cc741b3a0e3cf7ee17c7bea58c53882caaf3da3f74e5a0ed3ed15a93565e46c042f89eca6f343d7cae281e76b7421514f09f32936af2cf15bd6a078c04fcc8a9096a34721af175371c66a65ab620a5c6e9f46ef96bcb178303af8719cc93820d5d97fa065fe8dbfcce45cdd41731cd6958400b4f085a93c9d11ff75f168c4e0dc29db464f1cfac3df25e45e97b2972cf1cafe106bfedbe97bc60a20a8810d81e28ce598f424177e1fdafe88e34a4f2f17da13d940e0a6c37b85bcc7eaa1717d6bea71a1596014b61b386351070bfa65c08b31454e93b1ae93e439e771eb952390fb8ca59d488334edf4351d20c1f38818c4c35b1d8d918513ddf51d6d56ab2b714f706107969f9c02c90126db11842a005a987df983a1ec52917abc51c367d93788946ef3db6077bb68b2555a06484450355c936a8ebb64f07332fce394d6255a95ad1f6f7f601620e08eb5b2117fc0507b56fe42b693930245b0ca0dff5c29915ed34ff1d1677620b39295b702a8549cc1b57d5619211dab9f589766430cc456077c27fb3e01da1481ef1a4cd18c32e0b93e65717a0e23433e12da229d43315d19601125ff2d8241e003e64b4e5f830cad2e61a21333c539bb2d20c0f1841a7abacd9e4e9f31b527e8592cdd51b34447288a27f98c1d1ff00000000000000000000000000000000000000000000000000000000060a12181d242a2f", - "result": "valid", - "flags": [ - "ValidSignature", - "BoundaryCondition" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Tests/_CryptoExtrasVectors/mldsa_nist_keygen_65_tests.json b/Tests/_CryptoExtrasVectors/mldsa_nist_keygen_65_tests.json deleted file mode 100644 index 80857b742..000000000 --- a/Tests/_CryptoExtrasVectors/mldsa_nist_keygen_65_tests.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "testVectors": [ - { - "seed": "70cefb9aed5b68e018b079da8284b9d5cad5499ed9c265ff73588005d85c225c", - "pub": "d2fd03f3a1b7f635af9f34d580a98f524c735bd5ba2355dc6e035bd21765580cbb111923f194a7cc8a7bb2ebc5c0e71aa637cc800e6103b850a539b2a39e1b6d713e5db8314c9ae1f8bf8a38f06afb9d73b161b0ffe3a4891706ae26d54ffb496df8dc0f1983509500c9abbd28e59b3fcdabbdadabd45ec31499378bde849e7c1f19b7044d67e05106d7136d95380d5605d4465d877557065df0a75d3c28542f40feed42ec7e280637b083d988bca5f6394e02396c4676184fb63318dafaf5bbdde00e308fe84019c2340a3f3e1c0865624970711283356ae14bd6b94d1c9ae188de1a8a2ca824a8eae2fe6afb38d83a2d99996ab21fe3e84c0be6b6da08879b677374fa7c691b13d40fa9d4cc26b2288d5a8c9a43724381004d61b0d57ff400314c8e30ee796af10f7ee21bf13d08180465abc72eddb080c6a07184e3eedc47c19aa7f09d1f3309e183a2bd9b0573dde474a81ba4f78d0c523d0c04f90060fd571a35c037e079c5e210d7390df568f2e2f03ce44420c82f3fe69eb9b48ee90962d6b0f24440648f71edb241ee6566fc1a64cabf66be6fecbcb1387c82a7bc202d9e367998e2a291af0cd1570677fe8d63a3285a2ea6eb29af9dc1aec1c36c4706b12baa20839692f286a6e0321468f7479345c4d52fbdb2f06725b554b89e2492612681acebc6c7bada9225818dbc35d64c22c48bff80a730d0716dfac99dfd5b8992611d0c93ee90bdb260022afe25d913e06effb59cb1f8a60cbfa5ab2f459a16f467e989525e0a37ebe56e833fde55db9d1530adcf45846df281e47caa1e0a27efde2107d354cea0f6a454692f04cd838ebdd46e191e5d9c11839a2c3f488a4fc7cd265a7b5d32b08cbdbfab9d2ccd76222c8ee37ddcbd2aa063ed861473a6454caea377850b1a2b9ddbbcb374fab5b12f351c8e5888872e5cd1f60a4fae1ff837d192c22beb41ee6fa392fcdf4550ff46b5ce906d017ef3077df132300d8bbfa9bb03c75e79e2f04c284ad06a44399649c3e2a2a8d1efe9b7a4e0c271047ab75908bff7df9e30eca547745bae23a86ff9a8b58c2538b88b866401076902dc5f0bd761687b49eafe36d350cbedfdd36c121cf23786bfcf7e47076496eab6bbda774049c2ebabe2de99c4c24f2db73684015b373977496760cf9ac23d8b623133db2de10d73fa6ad1c6dac8434f28c6e251ce7293cff3f3b61efcb5a435123670f29846a13df3ee712604461f1bab8f4ebc836de058978ae734396a98081b35cc98188a86949c99270d4709854c5b35b17f48a373134c814cc8a0f3e2fa807f2a918530907864778282d75e03a41b2504eed816a417a3ac6ba16080c39b7310192002a728f7f20395009a9e16767ce1971f5de7d229a50613369e4382045a8e81901f4dba8102f3d413fe35b326a874f233b719a7137600d35d33aeb6b7259624083aa968730c8f78292ad28f14eeabe660835984fe69ef23dec8c327c0eb0b882d587e1ec433da85c9fd1e0a34994dea240c854452d18c30f496e49ec904b602e0f5062edcda03280a53b4313574cc2c0d5471bc9613bdfd6641f5bd127bab5b5eb3d499a33114048220e819f8ee12ca922c8f17d9c9f51ad5bd6883b10e6aa2483ba49dc547da7686151344f4e9099b38e430b5226b059832cf03db48fb02dba4e61593dc4576360491890e53ec0e6ac73cf32b25d823b38456e286505a541e5aeee96b1914f5f76687ce2b0160227abed77993594bcd831366206d75714082f1c46f1f4439ac81a57af31c81c555307a070ffa94e0479b784bbd88a60cd4c7cfd94e6afe02f6b21f72af0dcd6609d40c965c14e5f2389183e53de930f7de1d44215cf49144844e8b87f78a7f132aefe22be80b4e3a05ee3a68ccf609ef44047402e4493046e6f9c767ff8a75e28b3ce077fde7e7eed313b5bf7e460127ca8182e9bc794c0dfa730fb920080575a751b5caec85a109b4422ba266743f0d032bda8f1ca6248cdb917530df1302a5f8c18dc642d52478c98c12a3f16ef2b62b4f59ea1bb58de7b65b3c7153ce6da5e4950746f80e087a0e3586d097791bf36def865d68591d39d0903773eea962147f34704138b54df7924cdd8c333db5e1a409ccb2b34e2c3c8c7fdd3fd8d012cbf382aaa85e83a12f235a2d147d035b7b28b34b6f57949f322482a7d4d3b15045c420d5addc7f0e69b4dc1cba58b01d872480b06a260d827d891b13c4c5ca50c748de3c771be61e9aa170165cb01f4bf5da27a7791d3ad3f6267b4cb4e61b28fa1708418d932dfc4161880c5d3b17a9663a9061fa8f1804315850fe4e7306c882b38227e867f80872cdc1944d472615ea4900ef7d270b881d4130f56c5cc980d92a47ada6657eb6f37a385d2d8cc993e1442eb05281853636991e34aadc68954d04e7adef76bf880f059b0cbb55d915a4b123e2f1339a073cbfbc409beff6400ae096d5ae18ec42cffad5b4980fa35bf03413adb5d7e6876ac355d1c9ed70ca2b973954d12b3cdd76ac6835db96003ed8c4e288b71fd77dbaa7635720e12ae0a317de808c664e317f55275791f3245ca4fe5d4d41077fc150a6e403d5a208e46eadbe8f2cfb8af472f4a0ceac015219478e6b86c958cf86525b7485c1734c7ef00e90683fff5dbd0a7d413a855021026a1b32013a4616cbcd3700acbc705be3efba625c69a025267bce9d135e3f5b5cc8c43956407e84b6663103e29c242035551ae797f56c6374be0c798c0cf398f1ed", - "priv": "d2fd03f3a1b7f635af9f34d580a98f524c735bd5ba2355dc6e035bd21765580ce38d1c14f6467c35a9f380d27de61f7c75031569ea2ec8260eee9105261b7fe160c91344b0c6764c204e5b8d424650bec06b9e2e625af07e23f4950ca24fb4d6ec2c8b3a717c9311eb87279fe25e311f48b8256501f6463412b50dbc89a869ba2241112648400738730212442544575483725033356258423201621183610245665648356120845260685045655512724747212125402221428117650306426152134325243382121135623332074786223150837084264345645148311486246686743371366726014707721161588558387183806701657870647785600288534846622583548804744012574371077544387121142208887223588746148553716773822822741403577328718380781434875207647401607561060861322146156542670820841073130361028650452612166833552584735354526517106000385777812426804146432667410603554128333725230677821516317300087526584634638808846451112405321011181864782241003855754210468343733880078343787413576232688065864853483551585074460588700772013100875488142084166115605685115808058863018286131417220168171786585310622852822615043142885431780580115045688233663636406515244767064536422686750635413347851217808387655142313887566205174085281417213812608124414575018287101002132557042172427861117005304772132030216744315771455710541665741524024371512055116783678252533566424613702232740007068187175780286801721004275522864253158176308640831143305382735303723568704541157314123164326663562151508210302338172127102314227577283771627506887214187313030150715862866288868603270146172271385381703388681378810486573016523140830756821032312850065081630675766511601417121255564811411328826207476424482324775326081758115637483551478685666681732021367522746683445700666477204722285687124702480702542301257137367536005268153335820613732408717615224260185343116457761761566876606554781033631421832160155580423842031312343625273082812547513544126735001001838574424013036127812626811887435120627127515610222281118141666638208675561240065461127440345858781007852572885722222550840041260836462878467805022820771360751443687864313877737355412700540708286880045383432281006435486766501775761275438162403343453887216614704841431466587845820225457315213203024880801371255432720568652468040616835054533737272220680825508472867422361680075518121784448115645071105815511010471621075861187800527264521743234076486730776364875131638468745363842354661048363385214842038251103357468016433402070353221275733465833387438517503660880258758088316360182132261568741110331413053416726535501334808710264868845271442358803557705484287055888683862521827261177885176773005771117851106563570287401340012653451205467518807033356622620070232687726311133333814170622861514731302546511761580741613737061400548877756777665316726666887643583104875706764700436358605203442736486123721610624208608323540355557300610365342714158662558016531018261135468246132583477050060156021168545303687336418886334252015833423288568177555148481201581385041471835707545554552827313602123268321382587028585344867273428418220883610214161712415748852510260736761266172132360325411011226660161632642605186351585131425384566627833354507646508025434157357825430282384745701567517747803152750000947bca93c27d584e2c66eac9c7640c1ca217eef66dabbcb260b4c34300fa051357820f57392544982fd11057de233e6d2dd84972a7e47d4dba99bc30cf8f2ad5a2c0243195ed2730ffa92d227d153095972d4b3447ffac45a23eb41cbc87cdd1250a8a478b0f7a1d5b39aa2206e48645584fe7bf7a13168f482765e57bb924ac6d9a11369f4a6affcd169b7d75129b35d5134a31761bb8355aeeed27e201a06313013e307a01a73aea7955c0578c8c5e5a1a2d2fa4593facd904c62040bdb9f329933536bf8d81c4256baae8723fd4dc66bb5e7f9ca49031a193ececbb5dc390ec6d5513c79a052b3fd43612fb7375315d8091f79bab1318f17854561bc93ae0e5cd6d131e562c8114810c939ae563aa10b47ce4484317f34abd02d0ccad58dd29bcf657bbd9254b01ca9726091938ed32054b37dd617240f4434c1a4a8711aa3a399a8a5388330b7059eccbb6b1b9cf7187adf10b0c9171d3c0f6e2d460a419247672e3b9fea2c95910bf2fb6a5d61f257453b07afb64b0ba2758bcd735751f2d53515e236fe8a5b4393b80bf06df97bdc6380087e6aa8dde6e098111a7343fcdd1e903708e637ebf28323cda6b9405810edcfb3691149ecf224c50f8df92a94aa4770a0e91466194bb0e27bf1cabf16adfd351220033f76f5925557bcf9634e9461359621d80b4bbad7e2a6e432dc43b126ca42ab88aa88f0a84af58029c99a0248f0c454071f35b831fed1254d6f4e2720485786215f7c7f0c4ed15fa853cd3aa07259b39240a82135c2923a72b876fabb3f0f2c09613de39d459a07c14e7ba437d8041491fcec1433404bad1da9ee9471e17cb691b2a353710c9ffa4e5178112027764eb7de809c3e1f1fa4178a5d4dc9ee27857eff26b91711fc144d5a775b8b50d5db939ba3207680c242fc821947f934c8daee203563d28606be624a32901932dae85712af6c8016026927e9b8129574be3cb1e95332b052707ac8aa8f435e88b7e568d4987c6ac0e902b0609a02d91b3f5fd3fd901ddd0db9873bd7c71ed921d4577a78c4fcc9bf075203d38f5e76e74f277484e057b6189004131b0c9b1a155294d1cd3d5208e266901d7d314facce7e2aa584583a11e4d7c21b94a32e508eddbbd7a65aa86b4fdfa6bc285d4cff53926c7173fbe1f89cc303234b878c6b8101f58ac8d3e5e1bf5ab6b26297cc97b95954aabdb25be008a3f47e56487b00d3deda890d92c83957feac6b8291af65959e1d1fca3bd196e9fc9e67e0607094822e5b4191db96824b9f03f2ef57f5238ba7e1e84ed55b7dff3d6c2c1273692a9a19272166130db89fc67dc94db614e3e82ba3a3512b012d51fb486b5a3150b78e724e2a12de07d8671fba2da7fd5d147208fc3af653e6520fc40871af2177e65cbd0eaf304217b367a665f224caedfe93006ac1e14bcd67a88d171f3d8f3e358a71926ba3e5c239a531263ec9437bf2a033b8b55b2c0cb6e7e97316e22df77cad910d20eece1c50910a5cc32adab09377550f92d5bb1f4c07f4a2822338e2cff5348df77cf8ef8e6657ded1e0ce058e3ccfbf39b3f166e303d33c3556c9ac8ecb3df7c74ab36d0f2794441ba9808827b578fb5c29e494e21539ad3ab2b41bf161d7f69589d4524c54c89b486f75d252f541cc63b9e706d64a1289a2306c595363cb6fbef0a1b5b17ab5b1794bf27036f64eaf0bd430dd58d80010ccdada4a5a3a1e41a6fbf129d73779a37ae5c8d6841a9993c51e364e04fac8e25a4e6872f6c860fa265c1c4426ad9c21d26da8c278546adcd831f2b8b26d4e1f670623d95c8362da662d1ff0ab687503f328de095810ede12b49ead1533519558c1e940b46e4edb027be9da2039b25dcf7357e19e5416ae268c14fb3a8babcb3d23f70cc9d59681c5d833ac22e653d86e22ce822540755d8d243c15213d076c6b26436ddc07c7e001347b0cb8783dfefedf275fec4792686734007f0ff8540811c2afe6ca151420532fa5526a1074c3d789f2932de42e3acfbf94760f426d96cf033fa49e2f458f9a9c2e71dacfe009dd9c3f3c8ab3282d6f383b981c82d6364f0e4bdb2af6a95ba61f474150cad7233f8903df972dbb0328c0cb9d0ccbef883d2e6add180eca1b662fc1d2dbbddb3634219e1eff38b1e52875356c03eade942055f483504bbbcb4302a417cf6d328ed793b1a3c0969b7b3418f50ab39f83c5666c90e38356f7f9d494a6dcb63d67c34e3d14a4e15596497926c8568d8ec3dbd9c2e82c385bcfb8d9674863bd4fbf1757db447bf804ae950147c91fbf9aa17891044ccaa73b45528597462ced751d015ebba9e2b7cdcbe6dc05aa9eae0c86848a3475bb1c5744f5903ee4a842a469cc181271f245ad70d02a4837863b296b4adb4e8d03d82b64aa11dd31cdf21edf1dfe3276c4dbc877e35b15fb2835ec3a1c453168a38ca8e563cf3e9a00736cd5cfbd2841d10f94ad55799c2927e5461b28bac5174d0ce3f8f7cd7609fbc8da0c38cc21695cedad12f8d2e64951a8996e510d6d52797c5ba0eb4afa6bf2cc43da09de3179e899bd7188b32a98a499d372f3707ced479b0981cb50c0c0539cf7e3100b720e466652a4f499c2ba3a17f5232268730b962bc572c0de96e8c9e28f7e3532c2224196aa9e27688dd050d7cb7854fb3c35f9c62efb10da84833f29bb1be5ef3b533638eef743d8119ddc290bdf08b6f0f9e4e1e13446c53ed69805da26908a15df1c48e009ec1253bd5a5898ebb5121cc24904c8b10e24e680e565985076fda11d13ffdfa4db28ac9f0aea2f81fd7ed4dca8d3b2e3848b4d6046f6e0de3a4f683f25e0605e84b36f483c404ef899cb3fccbe8cb2a6f0a7e10b1948cd4f93f181555f661d31d426808bbf9f66fd60d649269ca3fe991b22428c37ad2a08680f747cc0360ccd373dc6a9f43a66470e014e72b3d8c38e020442d8aab974e6049374145b04cb7f3044aac1efdab2a18bb464d4f2f2d8143974c95eee856d59ec00288ed43ff5cc8803006c995514a2cc9ca622b61bcd75ec51c202a917105b4a4bed1b80146831dced07efd2ed25739f54096911b150d3077ccd731a0361682725d53803f8fceaa83919291edb4493ec84cce1d0f82a679236ead1002ae8018cac9fdbd246ff093d803c0de3326a57907b0dd6b01d081458c75728c600829928890a56aaafefcf7423b70a6d86b415b8358dd044abee00b9c9795fc8f61a64686df5f876a8f33061599ae830f7eb4c4bff875f4a936c403c5d160de5d33caee40fb718dda4478ac6f51c59c2155254bd77671118411e2609d000306fc9507004a31e8957ea40c2564b83c3abb71a87c11bd18d7891c449dbbe79b4a4fb048307ce0e812b2c68ecab77fd1111526ab0817306cebcb0497c552431ce15e4ab52283f679480d69ddde1f2579cfdbe0bca95fc5b2db0c5cc76a31950f5116aae5f02d46710e4257a75fdedf2f47ce37c203e7f24d3c9179713c5d807c296149a75ccb444f0c6f6abdd2dbb2985fe267482858a1e" - }, - { - "seed": "4b4b71c5a1bc1074f2167a1d68729cdb9e16aba3651ff02a0a0f4c883caac827", - "pub": "f8d4945a92ce46dd24d751da02f068482c69b0dbf0501634c4a247e1ecf98b270474c81aa0d8f45c0e8b5d02751e797d101904586782ea09f4e3a567c2bf5146dfbe766bcf8d0e4ef46016c6ed7b167490fd2f8e9c53cb42660331b1b62810d21477f5c9301d6d054fb076e77f35c1942aae874669e0957a031223861eb563ad723781105567445b5422b179e4828a4306079c4d42b793a1358b05d02d4565e4afa2d1cd32b6e7a4224d3a86e8ab79e1dc33a11d99411636f939c3ad0d39351cd057fc6bdb32eca7427ca0842f70b416db14518796f68c66e3cd04720da02b32a3430e0e027f48974602ebaaed0f1fb5763a914cd6db7c4ecdfbe076b0348da1ae1f67c63eaca5dd8c27ad54900779952239539dfea22be70d54661bfd973d1342f71f6a97ce798efff852fd789da56c867c1fd2317c8174ca0e0787de99f77d264655a36b1d8589b4c4c1743e742c31ad19539cbf8366ec188dd606392d727a53c3bc4111ce2cd330fa0e484f19324aa5fd577dbb055a3ba6f2e964371c0d4b9150e4eb9155db871b6a3f321db2b3eb9e679adca62ea6f7db5c4471f470d42d6c161cc1a43870e7bf845cfa696d71629c21d53a4de22ae73c39837222077abd8a1afdfab6b4dc5a2d68baf6ec95621bafe7257071a62f07848180fe4bdc29ce7caf2911564be1db7da45ee58852d0457456d19979ce66f3821c30539965e4c3a1691dcbb4ad0e7aa133185d2486860d4a5fbd260585241772b5976eb449a72494637db59cef54567f7fed5b0ed618c9527c28c38ba362621cceda11a00debb824d31c7d5b3599077b9ff736c3245f1f3dcca6d8d74ba96b195b51cdc1c68e29e5ead59cdadf5a05b924b2a790f80cfd8b8b17ae1fad36adfd77b078c5a535a5293696c7259ab0305c589b2986b6a841f21cf8686d6b186ea538c29c7654a6ad74daedce943627bf5d497cd7611ddd900efebe11f9e611f416b0694b621d4ee741cf21759c92ba8bfac90ed9d274a9eed59774cabde532d7644d048b83ca97bfdaef30f0b2400a1bb647c7bc9e60f57451915a0b531e29d21c2007aaec522f4129a7c251d7fffab20bcd5b0563ed78814a3b2047a375dd9a919a3e8faa0edff63e0307ec9cd14fab372e965324cbf541d99eb498cd093b188b1cb79dd6adacc1c9e306483be70c1bddd1f67b0b86daf8fd905f7bb6239138a73300c58ee30b6d48244803a5ffa9936b0a06b16eeb2a880ff2fbdda1a0813006c96ed0b6a30b5d10528cf5afd45beaa82369bd8254a1a7250048252eeea523dcec9fff069006b2f9a8653103d47ecf79bdad2572a11871c018646505164837dcf91c2e22cc55b344990bdff2d50363fe34a19c5cb46cf0c193175248ec50978f2cee4e83ed2b7bbfde4471859017d3418cf3d3822bccea6b8d30cf11ff008569d9f0bf462ce6d73f8c119e3d3ab30a68d467cc60a907661fa1dd47ff3977847be38abadd7d4b4e1b127eaa131bf3b0b1fafc57165b69a48500753b9dc141b9819ccd9b4cacfbdfe4e05ca5cdfea912602cff1ee04fd2914780e713176ab4383f3cedaf2c0b5e6b640d3b5905ec8ea9630bd3672a18135701e4140627e98f1bdc78b05d9f2224c59ab3951a0653e6729b7b4bb0035fc964c15086fce0c6ad85155b940c1aa13428f1e6c20ff95661d283f2abe3d43c072b169d68c740e67e3cd9d44d80bbf1d455204d3b56f06d9cd266a2a928c918f737a9e475be20f26d97a3c0b7194d6043cabcb8bd14bb4bfa94d13c0d9bdd4e6b062d4685d22f3dd7a2ea64fab53a0e06e0e425fd487e333ac6669017492ac45fbb9e2313f6bcbc6e484a5965e9412fabad6a6fd03675ce1c70158b33e17cd18fb44392f06753d565fbab2d4cb09a85edc20c9c12276557b03dc41b7042a0d7fcb5d236bec4b907f6fcfac62c3a07bd92ea85740f1a501591fb8d930a527fcaca427a61256f6591dc1f3cbaf19cf3f9b5ab5aaec97a95bd5d9056f5e463bd86ee03d1cd5a14312dccc3345958de85488d1db2c54d3393b8bbf90c1411a9a8b3bcf9a13305fc5af52818fcc4039d5c8c6ed87d8c01a089982ecb6feb7ad09a79603aceed01cf453b4620cd36e73b76b91924d9be973c8ba8b5b360998a182f9a4fef5563a0c5505b18110723a268ca4543039979231fb082a639658b9f5468e1bd16f96a158e0f39a160109a7cf244cad177b2b1f41806279296e7d6622425b75a1320e7e3ceb2debd1f739b29a8a3bef23d5dd2712a82e320450aacd8e9eee78a7d019aa09e42cd9923702086829308adf09c0d0a88b58b2f7c4534f75631af1a5b0b68552f402481f9a96b6a6a0a14e93e2772ec72d286aaf2cc9ec6450e80f42673a2dfd25c0e0d5831da8abd631966dc0688c38d602aafe8bbab8ff5fb9003bfe2e45a74a1261598af634f896cd8f4c04c5faa6442a788121ce8163a085b4e66308ff572cf005e960c8a21a82552ae6dd1addfe08ca37b82dfff782609f03dc16e0b862398c9fa09dfa4d35510f4ba7e77c0233cf923e4792fad9c5d7a05fa174438537740ec822b2670bf1f244280a5a7080b21ced5646f5077cb39f23555a112fa1e1458bc45c491d5092b763ab7d291b8c07bbea2e39982ca19dff6e4eef17557e8ef101d808ffb6ed73daeceb77c4cfa2e391cea50f1a75801c2d34407aaac4b5138b4632a710a40f39ba7ed36454e0b054e00bafc027d01303273dd2289e7666d98c3b602cfad31b7680e6b1572", - "priv": "f8d4945a92ce46dd24d751da02f068482c69b0dbf0501634c4a247e1ecf98b27b870452948d3fd91dfabba184b7778e2223c610196918c5ac471ffe27c45c216906a32e421ba0c8eb43bde774c8151020bb33e6dd3ccb67e07ff1508a591c40f29c4f4e03c0761dafaa6c4e4d7515d3d044f7e5d9b6f76c3523f07b86b966bc2050273654131572050232540265501410321121824027783508650550741845227675205140764772006807238701150672363522380823186775485346122741232101846044762034061346508846856004508217531847506553422270003465001318843366570722341256676412710345762503442766148802031700065838665810155802123526425443477780225517686668627385732838374183830578328430875075738806006057215372237255330206645686206532007402436187730431525465867647825811554786647043104375540063472868467521138444506855840850622072745156652883730438734305732524737387063014705036441133615604518408815122131125202504810267182170514218811002085201254838156820201088584847214346753735887361787368723385680274880675716073083468858754024781441460451718621650764072470876430018540463314037653043260254403334013420554376741651526887384367232437772872571236432846113158844048402448026234443446356631655624571084504437148135030305335563616217056075630605830233420552628432373442580105268442188606664005688153573261574404273251112701374300315715427425557365723036707713333154501238558575528577180345582234204444027511078611230842318434676756513328416871728302630727767221615188778420705148760282006015420340813653580172668162025543061257714607056886527838253463775286557467874302385541175163873125403136883123024782644056005776454050450463856458231030266773238561883245373725805362358236861886558048054373517006153723263352805784612747766872528551515675467320836133213785558662842164780507124010780705382731865322261671658563251820625605486727154222632331845371780377110620406316868745534211605053684662067164782272500355338031585232841457166288521403104854878437265654262373837268281560786012704588254043617732675622047062353066104016602755704578677260376636082632526506057173816361868253348168171755151062823522066020418818632307513542804243556317063765822868038468506613448543036820231730106212347485234367884828616827033357121850832050360848747865116708334325478114764064545882530235517784101378158280387668200424153038757453662564868561401622005841426338428326845853813752150205647048731768316114171432031210530176405308626212315625877622410617144857321075301351544462610553051243543667566675865335022131344837646363774338358017020828322812301042686502414653278867536671246033825211786357550517555870412326345585188457210000315518722276643085112001162624655523063655320741885067301234547663482785273242871867433610317833314257358238168035870421442233173234774652833582072540045143452135211450447284405865524301678168533008608553068110010402510031273465112253237686727627477608688360860655175382170833104267041778753258183846702848155552758183213003518102058824468267721170670211086383333614167717873621734000234476376137205763060645015200727731656541667312526120835206388554240354487387761200858280506664805026810157822733523020574251831872646604616365770712618804337567105781aa2bbe68aee92ffd1be88d01dd90ebc8d1a9f5da65fb482fa23e92a0bffab2416637956b1a4f7d0e392b910710069fd0e18eb26e6ca741ed0915fc9fce0c0ebcca45c7be24649829b0ac3a43c4cc2e4ccecc827fd3191515df2a120359341577baf0bc05f8358d518a57ed3033a73b8230e8b23f627f6145afb0ed0742146c61a21aa6ce40ac75928f007f39e2696383fa48c75694f106e623b6f41e070d0e985e9d542ba2b5f53a47b00cb6472f9d03c3dbdd1c113b08128105f6fcb281c302c0410c32234e0e9f279ae96f3ceb0b0a490443a8cd46bde80aef7b1bf7df48f98215b2f556d0eb916695417dd643c93ad1d703cb238418c6199f7fb4936cab6490072a245577fecafa7507a2abbf3e2d185d9dca22ceaa93662168f43ece8421b7a9a5a2226227f22bb497615426881eb9bafaeb7e14a177ac6102425791a1511fa9bcf2b3e453ca701d0c8ac45714541a0478353173a6ee57078f1059517910bcccf0c9842483cc8e5d35166ac13bdd7d9c760819752ac40cc61528f4a93749bf5711216101cb0ec79b6e0bb92d4f9042da176e6c175ea1b2738b7a6355551af4c11aeb5ba92ecdf28e521e1730598e480a6ec130c65388fafaf5bd3f43f566d0206a6ceffdc01aefbf52b46bccabce80af453d1ce840b3157d4b1d15ddbf0e864939a5c411b471a9077e5785ed9928ee1c05e0bae9d4fb8c9b0b7a814a23784b04f63bb5a533aef4c186217a24302e706af88d4f9e85b71ce427d19c149e01ac698ebbe6b5cea2e3a43df2976cebea3c96424d2fda27dc3dcd7a36990ce7b9547f247039e83194e34b3dcd90d65d3641ad5b90c4114d0441fa46fac16a9f0691b36b39012f2361ee0b87c23fc454b21205ae0d7e6d9c162061924c2513c369ca744dd2ddcf9c0c314413d4898311080757309d5aad1a3761a3223b60f66b0e392f821597a011188bf35b25002c298f01d6a5463d3176e1c7fd0ff1a70e112adf9230e9fcc9c423e310e67c35860a09cc4d3dfc4ec0b16af467373faa59d0e326d82b6054382476a1d47cefd2709ec829e3b29ae0c09e6b41dd540cec37f0032c949b9298ade79306e376c6184fbf7440c14d217b1a557886ca79af8625dcb9142126a70fad6f813f3a5625f2e138e625d38b399e20ad05d682552180feee5c1e370f2b6e6d5720ad313b98bfd466468c727dc1f2f1cd141dc7cce3592a46fb3c63302932b832f309ae30e6714ab952ab84d76a59306d05e1251171f8c7f8b7b2abed123d47428741a8583ee5b8e973950b4f5c754da4679f3a06eb18115c3049de8e232afb65747c0aeeaf5716fe5b89ad6ace90f8cc4e137a8d9c65cc3a98c7fbaed0e7451a8f623890538da9a7b821d8cd9f49a1aac810eddd7ee00aa8cf342f0491a50e617dcd535242d54f0ee8392d1b8bf7d69c81fa335fdf4ae163a1bb7024ee883dbff9a1ce154f4316d6063dc7283f151c4ecf5a9e8d1c25d0238cab9a925788fff6bd68519713694b231a07e826cfb6f3910428e3219116782e07e132228b558cd380591866c028e1f3bd2327bf7c61fcacac8485eb43213c20922252b2931861e077712cbb5701876bcf66faf1cf6582d4f4eb87cf82c1b7807a255e73ded3a7fef23139de96ae800c2922246a54f3f3a6eba2c8e8388dbdb41a4131a69280924f6d7c13952adf9f6131c1d6ae6a3a085f8fd5e4a45c2951a8d65c345cc067b13ca32b1a6c28a6359c48dfc119ff7ae92054169dac29119508f17ffb0bc925e357af70b85c214db0368e1425ac878978c346485cfeeb9935bd94d203e271c2ee9effc63c54b6d05c15eafe0d0d562c458b0c7eb0d84cc123fbc30eaab78b47f9cb11ad7acb54221f56998177d85ebc62deea042e411707fa78c545445372461bf5d4c9e4b5778bde3c9db02f697965d2cd2a10be66aa9dbee728b52a9117c53a5a2d90d59f86d8a601436ca41d4a99e3c2e66261e37a3a5b7d4dd21cdd46eb4c62268520ffbbcaa8bf3de714652cbf83e7e2cd57fef6abf8946392a33d984fe1cb1a08fe5dd088f974499b704d94f0646c7977dcd7a75e8012ca35e39ca7ee7ae1c0c27013a32dee29cd141379da504cff6ed8853959840e829170d2d15a265cd9a8ba48718848473090f40c1bf3dd4159267324bf9858400091fce515d541f6608d395dee9c5f673375e443f104339f444c4819a630232ea7d413cd8a3556e60d7d20ed42e45cbe335aa1ec684cebe7b32c5bf4f68f969932961930247e2a9f279f5c587120879f3f61025d6b6dc617c9fca4ae8034b00c8dfd6797061a36c12979e85f4aa7c9f7e57fae4aa44db1af6306e982a723b6f58e9008b4bcf4a948fb131d08afea9b4bd093ce76f8f6366adf4eba4e31fc5ee6df22e1ff1370c81937d29007a9138904f569b95a38c5de1bf03711c9d41fc0e72744426ec510e600d1231c99c7fcbd91eeaaaad1ee8a27544d0ae7871b4b881d80defe22f3188c250ab8760277be2295157be5f33201233b53e2348661384134e6a9bd89e8f85b2f4e217368fc86161f491413c8959db67aa5d51ded0854fa779ad305e3a6895542cd84da2e8f4739585f7af91dfddcb35f7e8c6f90d1eb810d8abd36334aa02e84a4cb0df03961f5aadc0cfd45a7f59678b06204ce0613f040f3dafcff3d59c56b655a3d3a0359340a0f91ab9ab1a17621a1a57af588c31385d44667e9258e5870756aef7ad2e2b3e3364baec218e0d6be14ea5139fd672755f7942f4bf9e023acf94b1e15c58298e29b958276f0c4f04631d41d99559e7a7483aa39252647d8600d33a4c8624d9a663afa8c927808072a4c6a63b92a76f76a79176261d9050e890d52ca68279af0b09b443c001a4092531bb8e251f7adcabf4e49dd1616f42528cd67283f2c52479d7dff2f383ad7eed58c1621e4dad50ac9c9fa5096adb9eae77b19122aca00d48e967050303c93d90976a3ddd5b3ba4a816cf0019b508db2e65cc47b187c78432e41dc9bae328ec529dc3f6c6be048ca843832ec04348421113a02b60b35ca66132059d4d5ec297e9b92e8aa3130e30daad74ee7e021541f0b3ffa72df618969d18b7c6936242555fff1161d85c033bbb934894825be9271eac5a445363743f81c46315f547995d6925fe76be6b7145d022ad1a015c0b8101fe30a81d363b2bcd627bf178ff12023f1bd82665393a49bfcc5aa1f1c4fa318736a301d00dd5d015a14640b91e104c814056892de7c624240c06a3c5ac14e565fe5fc6170bf315913ca6f5bcbabeb9c110803e12d81ccbef3c48b0dbbec02f8616227ccedce48437d801861964934b149ccf34fdf7d60d29ffb46854ce5f3929ae9b6c051c6825399b9ec10a9bad1586d2e75daac68ba2527b021e3153f419b0ac23a961799f016a37572c91ef790635a1d7b7e7968aa570b5897c6cf03395b5fd2022114ba84df417f8f105810384baa41eef2a5b0c7c3e320237bc67dc36809cee73ac388fc9a0873b2ab63b638ad364f28b1b7d002ef2cf5c" - }, - { - "seed": "fb27dbbb4ed8f4f7d2700283c2b092866694246932eeacee72db730efd172576", - "pub": "0fb4b45d59d6ba35576d1f75ecf682e5c901372e65678e959dd61f6652ae3f0533a0be6a3bef98f0a550cfcd43cb1cb9ecc3f4f7db656c9fae8122a0a88dfa6262f3b11454457167c1da30042867a37b26ad62d594591bdfdb36b833dc83e4b8109cc2ec0d4126d24b2bea48781fbfdad7659f1d8e60987b9722da54627eb895226b360c61fe3f2a10a69cefaba3219afacaff22ff5bc7b564b01a65bd698aed8a7ab78812ea6960c2b766783abfb85613b069a7cc173425f701b62238fea489407ed3f2abbf538b1184996cc7b9af15fb5754928f552af73696b18fee24038a1e9a11df0c78ed6814cef3671d60dc38d483daa6a6822fb4381fc036c805c8d2b7151bc6a6b12466211c0e1ee663bf4ee737f4d942881e9675fd7d87709b5f473054834599dfa499306b3e727ea6fcb7990e0adf348321dcbff6fa886c5846b1d05f5e08c6c4bae416fbc7abc1867082834616e3b4757616e9b7e04e2013b534258015e06a114192f48e3c5f0e6a48775ec05f554d69843684ffda6a2fab8f2138817596115832af77a10e43a4ffe98dde79a9f80c0710e5450b681d620bce626fd0932b4d9d87be222b7d0d8fd010172f3c5bc2353f44c08470871e38eb3dcaa19c92d3d028d61662c54eaf7eca32c0d48f4ae0b2fcb0f517000a8bc96a76648347687815254ed5905a1b4a2ed4e43364b48886fdd5b86f90659aa03b2ad85b54d3e85e3380fa2e050120f555fbe241b86e481e020bd0ac3445cce71d9f8ff56a7475b073f1f388454b3605ea18a5e183831c948241da34ea3e1112bc706102854423a4dc16d9d3a79bace600f8098aa60744e1c7fe18a047bc7646da4a569e0a8c41d0587053a22209371e4bdf5a7ce8241d97670bd81e7fc61069292bbae13d8f729b7f5c2ed3e90bcaf55dcde5b20ef92e1e7a159b6205e7abf72571f02505526928db09f65562d628443925e7ded9586393ddeb4e59874077cdd4f7fd4ce68d2cd311de78b245872ad56078cf3de1d88fdcf541af7d6cc69a1c96c2e5763be310bf77283a820359cdee43b53b2f004f2fa2f1725bfa6116ab9a8f37ff4011106d1e65c6a3828af1e92671953c26acaacbc48031d7e9919da915b9e5d89556fa82e9498a0ba980892b9b9427b848d095a0baf3857b6d6969e99ccc337ec6e166b1e1f55237becda10256c8d97a38b21986ae06da7c80a17f84bc448f9539bf3630d7d01e12e80b616f5f98c47170df5e16450d393cc4542fca66359d48b1c29d4c997c6fec087540ab588663f5824a4f09e5871a78e06c18d3a708cbcd7b4a957bb69818d38be03888bbd62738deba58e3a6db3ffe477a5ee262297f96c26acf7cc419cb7f3ee8d09e47ac1b134b6aac3191f7f586b507f58ff9afd67fca0c10e7676eceec78132eaad0f8b91588c62658abdba03c9fbb0630b2e9603e5a93f9a04a3e07a09fa0b3ac4861d368adb53e8fca932f997952afc5da4058c48ae6f9b634b624e50d2db8e3cfa23fe41c2b88c3c588fb22066a0894893d4fcd55ffea4352f8a27d7714a18309b7997ce71ef16ada021fc52f3652561a1d6518559c250cf1e35d109b04408c998e457f06f73349cb8beca963ea4dd65826141a59fe60f1de7f8d8a67f5873a7696e206e4eea9fad9fe00c97a07f7d7daff316cf85bc1a465f61a381b2edb3eb4053b8f134b75df5c6d133e7cf38ae416d24d4ac66ae61db1f682a6b42b26a421e7497fada9a97717d2a9d7b028facf01ce14f3f834d84264e688bb7c0305ef9ef28d5a0a491b0c4ac763fadc1e260790e0ef2a70e6bc78a6d3a136e0efa5d86c9c0993f3e91f5ae6da55bec8425f1838298f63601b4e9e71aa12c07d2fb6c0cc5661bec9a0d929fafd8aeb545b729c7bff035e67ea7377d2162622018f54f780289fa8bf24f9fc2e85d06ddaceb91d064d4ddd3969fc213af6292ef7fcbada5cb3d5d1b5833caef100ec657056b69324f2e5c3adb519120193157505f5a0c1044c0034c03a664cedc465c79bc2b915b749ad0dc2e88deb3fd6bfa8ee42631f22938d735186caf7f273d9c8361851028362f54a9cd50536e31bf835d13dd4435911cf01b1a8e27339033690c35c311760dab34e391fddb690156fa47b169043e6d5e1ab721619ca3b8095194b7802a7fdea8dcab9f43bcfd1f5893eb4f58edf1c0b9ddd0bd4615fc1eaea46c68bb84697df3787775e4df560b1a43fbc7a33a3e084ed97e59c000529cdc1f97eb92e9db331eb207ba478e3457d1648084d267c0603135b8dacaf2c15b42299da433c0e5225c934dada9b701751abacf9fc47d90cee43a2fa47f6d05d169623b369a7133d0f73922b2eb869e91b5737fc3a2de03a3a92da98a253c022b4466dc591772d39e04cb1e4f176c1a282ba15e912e2e5c8d81e00f92a2fb8bbb16d6b7733a785f620bf52557b3c3e87ebf625b4fb0b7b65101053532ea099a1b0264db218efc19ba207203089cda1fc2b32bc416c454a4bb977fc3528e423a3553abe4c48dcf662ba7f5b7e1b2a4e2db9a388ebb0e39bc229af71ecbf2f40727d6cd39c2fce2464aaadeaecd47bd08fb1fa5b6627d274e3d31c078ffa3c3ed29980941ceef8853704262b23dfe88780fd9cf259efeeab01255f0cd354a473848798cc5c1cde63aec6af2ef078777cb67a4bade7c3d5f345111fc73261b55e8e257ec5824cc829b5f5ee31d4ed03a16590396e2fc381a7923e81e3f582252eb19a7d61ecfbd72f0c3c16fc79", - "priv": "0fb4b45d59d6ba35576d1f75ecf682e5c901372e65678e959dd61f6652ae3f05e8f6c5312f27292980146aed5bd4cdcccf105c59dc052e9a5604839cfbe13920a93e9dad0a618e59915ed8d751e04cd99bc661e5ec654fb33c82ad84eca806453b9145c9335e1a95d987d85954a8db9bda8280ba76402e489afc07d90df7567c36560273017280466156464484345270285178305711250242618355037451272805831334710075688556205675635811344085746515547468075008004432316642077378448408234860066117021246184447148263433760087826350221845428303755534425555717783464144721524485283480133537526651561143130746043842062162336620037333860708821510700458474260707108783552112553517880140325080003741440347208756274083066034241155117413308076178401187304037688762030146873725228304172627873352187338032728273353058572467830523107526832557771072150587632044015331378888724574122703235400051288424471463017425114740686283126323770788487586151073237435056574117185656340627503508855871406032154132457173517406070365623071357215822006317662446377112741371334240268625017522547202654825346782030134741711776706347452824240741863480127103262631840235133582166006304237018151562258370018144006703338563061314556680178581266374583457127838148005138183311168871835130403368588740370785287432187408630065074371213480444706406001571542517601870046628537585864013505382654286745611688562826411460181216012170130671033666664050228621047288450184107351840765645803278162817607642382073553002556568788426586683475530285773666151835665516303380616363227666858618761871385373345822418160086702271023726638411777186012145217307263853282062146678035810787254502315346844448377284120122775352576074324353408540721484446660113184477760757722801866776724528834717535547588852626733700730625755854828563408352458634703417047181611758852002888110270451664011082677250413015718850326577835815683880356606382152683807252371042722116282841206422056134168747282480661425448572771268256417857244404004266015646767320855751075500451662804257710454343255256810735615778555006233143718626653125262772466865157188155020522535172225206165001848253325225481217513861451643867711572822836715814443656054847322127382261373454384541346144146522301347070057540552088832373200502381445727625633138630426301227580101874474535184582276070136541128502418006160228766041816107568722737402742376833648820075260766071780446008477251682432221347088684304624471851307716637632473404150070457208081263267878825854610503616057514005155454106025132382716413517273075776773481460567806534468274677273732307402176400528254003850741282758634420707000148538120762573172316826678588360778452648825333124015705775726667545085706211188383356315880631315705723620874123576711420723155615800885213201562654580242880636273014718214588481101167063874558732715713124774232421012565602130506631727226611188335482535363622858870107022383508628013502852406025771446035382361661005267412153785415157213823542604756172745743260401151135822128877563768657521545878000334705788040273517532403014046181623871830487143472731360310027464080371511476477842670552846448716276586070267871218265501785588404888023122544554862135404377441518c06b6969446a99968141308658e13180dbdd324d01df12295072b0689ad24b8d909f5b912fd4484f8715495095e72da498d11e17c8fa5179c034d020d13333d45f044fe079ebb5caab5ae07027dfe0b451c647a7cef0f2d7a516278d0146904e6bc5f9a019946f64f3a69c8739b47fbf768bdc2d10ae0dfb3ee486115c3d29d0390e9a6f0c66f32d20ec247c23a95324346e87e5064a651255fcc49092b4c7e7c1ff85c6bd646f40ed3a8c0bec3eeec4357dd01ea975523e50a5e1f1357b0bf59087f056a70aa4757348f5fafff7bc3388da206d92abc9a373472e188b55f03a2f5b2243a3c2ff86a3934ad1c63ee4d31ec38b980f22141fe77b29cedb621b6e7689343bb29699febef26346177be01999a5a1a916987138e7b84efd5a8eab3b995c6e4202354b659a391ee0305dcc82347c50cafe8c3d25d5bcb25648cc4ccaaae062ffb75041874fd14302b3189c8ef04500eb3b9e6ab7e021647c79e1fa19be67d1826d3b96f3e6d49c6eb5859f8efb241b8e583005536a8235c5358a64e894847194a3ec4cb7bb6d445c66c08ad99d4be4243fecbb6f340e175cc9373fb62abf024cd913f03bec9e8d28f7c8587e1c3a7620a83c3d4c31dddaeee9e1c965823a2f143f1f295b4a9665715eb2fc4a82ae0e16add7f58986e68a720783d14d0c48e92467b3deced57a169ce42e9281b180f791c3a9a84d936bb4cbea671510899f35a4ac0ee2f8547c2685913069ffd11ca7dda5349d545bd5705bb5fb3e233f11a6a6b21dc638a4410ffb2420b123cf8503ff4fb53a19dd70974d90231b90914f92e52a38b13800c194427204d3af3df2436ad50f85dc6eed13be12870fcb051023505363e848baf4d01594bc35a9c35dd23a4986ece378a425efce6cc49c65f5d829d4a7ac4ac54c3c4766928315f23400836da42717accf7061cf91bbbe8c47127f5a8dbe151b37fabf6477718b11c3ff2cae39246cf44520c92411a2d9b365570462f2545364a6cee318330123fa3389e732bbd135e74c6cdde764ad713a40f19eeb1315492378130247187c9444d7e5ab0e56bedd59ecba7d27ac32618e1dd23d1452664d465b968d86e53dd0d9b50abcf572bc1a2b072c1fb6a6b2b4dfe7a8261e5d074897ee0abd4e82c53624cbc3f94879323a4a7def36e80e579f824129d379515bd42f67f68d2a0d0d212d102b19d2d1bb4365c0f5dd6f6fa2f32010a9ca755599992c68fc61e4528a68a38f6ed6e70b45e1604221c27060f6336062f6f85a846e9586d8d9950c0517905c23bb99384092e333985d1e8f51f9a1aa6ed855b4288674d02a04e15e8485c086f952b746351755f31bafd9bb9d0ba02d7d23e0915b8a1c5c2e8372fd6965edfe496ed5a2859440b1851f2822f1c199c041e863a9d23ac3e03d510507ba8b4fb7adb6f85d421b0ade9b3b6606c9571e49ede3ed93cc85a23e4eda6d014b9f93e6b38ff145c8b10bcf6d019e8bdad78b8fc0c70fda4b21ce9652cad055ee62c195cb2031847490633f9bb81d1f2b81e9fde6f8101cc0e633676d5cc8b0431b917ae43248bb2749cf38561f409ea1d509bcedc177601acebd99dda198f4e4f215ab890ce8cd9ae75384d27ee7c3460daeb72bd2ba90fdf270fc05c52da014bf09f1c30def071e1750e5f9218f57deba0c90192d582b25a63b18f84e4e06c741ae8e125753f5fbf4e5cf08d64f6bc8a155b1bf4a6cf1a252a8f6167833d3895468b438ec98548a3aedfcf0a3a31cf1e0d4e442b6fc59c86c10287631b134cdc1832d83ac335f04d10306c75c1a45af63b48bf8eb03f89ca6e0da78be299f98891922a977e6ea182a5ae7b544d2666cd0f3cf2387ff3c5e4fac94c220bf532394269304fc8a57ff17fdde31b6d233a0eeafa3614dfcaac06bd6cbef6ee74248dfe9c6b7a5a0f284a0cd4edecaf3de0b4589d2408f851c2036812c7d46b15f67e8c9713adcdc1f1b2b82ed7da48aef24df9b400bb32fe89ae95608d7164c377279f779cc1e8fa6d6ddf67a264d112cf7e0733fc450aa97b286eedb959a57bb82afa333d1f0cf965087815023b51b1e41d035e29aa99c90cae7e16b0e7c03e52700cfe574a165460732537c413c701e69700ba941a9386fe8f71fccee6d3c10f832439b754b8bdfd49e3052c0ab1dfa70111a4558b86cb6054a4dce74f81990850acf6fc778ddf25d395527577d9d0cc34c72029aa9627d3649565f9013f6dd2e586824ba63c18d778f6e9d8ab85682dbdd723315ac9dcc02de0e8789f64f1db1a7f011ce71b028bd8dd3d1db7c2496e67838649df2cc4e4ddd1f5f3308dfe57dd1a5074c45f0346043bfa4d949aa2cac83221d27ada31ebd5a4f458a54d128bc7b20f410bb6c19f1652b84d05d5c173261d701d5eb7053769ba9c62362cfc52ffbbb536b1c21c497732c6894f8feccf35c513a14ead53c3a067585c1e021ecc3f023df543f624defed6168c92c43b0858af64da72240c0baed28c53c59340ae604dce4e4e2b316faa0b04a39800defb5dc91611754b00fc9d028beb2732568ea481febbc3324e21d2c9a3f8990dd20e39806d90fd50f1d19d34cfb18aceb5b7d8810b57f79753d372d0e7f4e14a6bfd4882a351083ff53df1505a5973cf63cb015a38cc8f595ac862ec9fbcf3a3f7cac508e6a48535ae97a56468b874af26711cf989756757f8d3f31cb1a22e5a06b86ac8ca86d4acdf5815f52b6e3f34cf728f1c735ecb35dbbf9b0fb14932d3b1816bba6fb3de65c1f537c0a36579eeb49f34a82881fca14c2d6d8f2c7f9d9daa879c8bc0cd3169489f44303a90434e8faa1387885286b5f837769dcad8f8b654c85c6fffe02acbb7c2881a7e3a3b2466e3f12ec79138a3ffb47c7758dc2f7a6ad0c76a7be44604cc264f8ccd1027812ae9b47c94b70c27df3f208231879b72947f61f98aed252698abff431c37170bcdb9d5894fc0f580f7260720c389cec04d82f5cf60a6d3501554065da790beef3f18a2f05625d0fa18fa51f0fe8d1c0583933fc814006ea9d3c8d94465e5ef36c65f9333b08c63cd0220b98313a465f5b25f406ce4906e74bc44d3f7a98211a0440a8bff2acc2f6fdd48da95a02f110d809a0304a756bf23eeb96e2e72fdcb5dfcebd2fbbb293736064c39c45209001fa2e4576ecbe80bb7b69b99bbb8dab7bc45a1d39f8c52eebdacbaa68650c20424b6d77fb03b39698dde6b33860a485cd2dfa29ee384b7318e8db0a8a1be5bd032f75dae98c5f3993da601bc00fd13bdb70460635d4dab8c59e1a1b74cd5564501214893c915081957ef886a68198aa776c29be1eb747caa6f68da72543a5ab3107f46d6259f932f616f3abf7414516d59418b14e95bcdb1d5703131ca20bdc8c429532212068437a90e8f992debf36cd1412ec24e9029d83c0dd6c6c049f9134f45968bb94c9f8004eed39378fa089241dc3084e253d42a0b9b91c5367e6be1f1b35c37699adc1ddf545a1dcae0f0d002f21a32279dfc1dbe455cf17a7fffd3ef781e727ac" - }, - { - "seed": "334adad056f76d74941fd87e5263e449d97c06d748a82018d0c794154c20a870", - "pub": "05f90f8fd12be86f4f09a59e0a0873933b75a7c33c76ba4cbce5a2216610d5a228e9cff23dc094b0d3690ee5b3dc55f243f2fec1db1046ceb35578ac48f680f9f9f8e20b4c96c67feeba4918c4d7ae555cb82338d92a2f2a97b722f09107ff5ddd88c86007fd3187e8ef195b678f1765644d5faa99773f0188daafd9da6ba2598d440f2639bf2c0a3729078ca78907c54e332ec2aa6d9e79698bc72d082787d7ff28929ccf6fac633b2efdc7dd0b82078dc8cbee7709512583eb2bdd9177c4691d4afab887a739b396b308b7004be2c7e9d83404d185dac00168869f5882ff81c9c65fa6ab987c0b356c56f3e8adc931e780f2255c39e2d40c0d741d4266b1460344737457d5dd07889b30b640be49615ea8ff6cefb05a17ab44db8debb3e883e8682158f566561fd4fa8027a04a0153acc065eeebdff09138f621025527079e7ffa9010fd95c8791ca36377b60e2f92383841e15c8a8ba07f2bd34f78d9d2e6825dc476687aa780b642b26a08c33cab33860ddd1858df04a94c2405f94eac54a005ae53b7573ce87860fdf4a59f0e96fd87b451a2a897d8e9efe4294949e8d663669d8474dd5fd5580a366ce9a282a5357dd7b96a66df961484072ef21552cbae892bee96330fd3a2c55008d71d23a4f0579bcbeba343c65c3d565b77474c178df9a97b451a4eeb90041db4b50baa022037e1e60d98f4109b9fa51275a7662babbd7c6f791f54ea56752e20284b56cbb853368a2f54c02778bdfc742e8fd566ecbc97596388f9f823ca2eed4cfcb83084749165b17425a8719f4822cfeb3040eb3c8611e1322799d5247fd27d403c74a80fa0a672fb1cbc62443a222dc7a1e783e5bcbfdeee18a8d880c65b9e827493c318478a6573533c4c36a6387ce1cb01ca70985b39088aa76f4c13a774da5b86599dce9fe1a87d2a48aade42dc5f1849ab42c8877b5936ff2e53d860b54918b02617fc78cbd03765ea6d9f554c8a6de18d7aedced60bec084bf93419b7b5ff489457ce976625236cb16c26686c3bbc5bbf2e1d37c69d70976a7a3b332dea756b3b84fef984bce70637fc376a8f4a02ec317d4e67a3f259141afc2b061d48015294497c276d87459894a80b2c7b9c46d988e6550567ec4f3035e23e1921818d2a4d060552ab0088a27c9a022db688be947c231a99f22d6d0b225ffe5cee23a5e89789f5ae58f4c50603b37a0624a96270b849e867366d8d82e02445773df5648a15c857c6b04aeb21ab4a04a0552e9f30cc253b2fe7ce0071d3335976bb702b11716420b43ab11639589e5d5a3e7477b95e598208aa46dd30e1606f30da0c616de7a3cc31653545894fa958e8ddc026ea1a8a8b807ea45297a04ad11ec7fb3ef4da1377bc6c36cd3e0ba08fc90b4b80c541ba6a5b7d2d91e299d4aa9d854ea59f45e0d76f8090127e8e834f3a652af71f18935a58dbdd18e9384eab5e2e10d78cd57bd4ebcdd45bd2125f2e0896bce153b5f84437e076145b61c050f3a45c1c311fd8d880f38d65e89c4302fb3dc58c6dc1f58b0c52b73c00a421261ab5b9eb317c79e2f885ed5734f638c8eed36081404a048c26219b04e526fbc1d1a5058685af88028247d6acb43fee3f546ce2bbe4ba456e6868cacc2557c07aca318e1c8f70af0c9f55aed0515905e775f5921b3ac8eeb5137182f487aca7dfee88e77954a94de3ad78c518b438915fced9160a4cace1d7a005fd60bd34e1b328321c22f58e70741117abc5f819722742187c9d3dd19bc3b7726dc3e81da040ceee823157a14470e9c0a04dfea594a05dfbd1e256bb1524fcb591786379fcecc7545a875483d4b2e58383da1807f5222cee95e21bc52316a886590f55becb6f2d5f8184330c82bb50427bd6dec0c5e164abdca44f77e80231fabfe8bf02012fd377536babf6c7638fad14870c97f1ab0d4273dc9c4ba426169b659278a5bac8b63e4318a0e85c4b22403f13c9e74b03633ffadd939fba9ea3d746b37e4bca503370dc6ecb7eab6537e16ec64daa24c1acdd2f98531c594ce745c70cf3acafeffa1d36cc062d4faaa76afe291b8ff281ffd546f500786da4e05e7ade2d37cd519bd78819f27ed9b9a950ed2d0129253da2b7f3f660281c9b0183e5f753fe96d123dbc27ff6f56fa5465b8bc9f48ce4aa4963d17fcfb50fe546164f901b04abd909b78108ed8c5ddc8bcaeae0669b740e0f7dcc833fdd91a789603fa9a2ee551a387f944c3a032f231ef0e7ca775905cc5abc8755886ba211e698211ecd3b04b959bdbf431a454a08558d4cbff01d177901671831e2a0e9838e7d9d0cdf1c6c8827e97cd341dedcc53097c9bfbcf0b4347e398e1132c5cd5a505d45f6f5d944073716672a2b0bb6c41c8ad65f843b1738fadc6018b4c8d6d5b2e2e331b8fc41e98a91a0f43da608f49ac0126561625d21147bb3d5a9120ba264a703d5e37494fd4ab883dca023a73df9affb4a3930b5aca133ce57920207d3d1642365ee718c430b51ad7d4fcaa294b1f42d8bdd7f08c5b8fef631ee7f18904eb84f867b7407f93da884128ea3e4e1e9144ed351f40fb460fd511aaef20ecbf20398c701717409289ab22c2518bd464d28d76d9420af9c9e91734e36f355544a80e50be0d3a36556620d9d217946cee219c990807ec0d1f2ac904cf661f6906d58d8a8f500c3d54f1966a8557f8224415f17279ff93489aac8e8c09babe490c6f34688ef162133b19b55faba9e3ae1e2573e51966ca827e3dad50ff9", - "priv": "05f90f8fd12be86f4f09a59e0a0873933b75a7c33c76ba4cbce5a2216610d5a2b3b647fe6b2d597c0bb64bf8ec612afe415bf8c6ee9c1c89bcc07825bb4e0635e279d6f8dc3e90fde70867f7176f78c7375112d6738ccfa4081c0a267427e6456a9cc1b62d301b2e61490266cfde8bfa6105e0a538ab1c1d0ab74430b33713623581386483755445243753473438078511606051368073160115738012354521300214633143005060458451614181317625600850828658142078641844516326445870256686653680383537701272643265207087826247876408370160122140768874166087151412676620180320686408856302667266662275523315434588681761074568070028312208584121154004344663581510807865182675883813108000025672850572778605381322036260037871137460676071517771314675682566577436544573460506504832281442435167233455724534277207215216360738167150836460874031736450610842824275257455405400364275587451282130682375546268016543663485208367258707108220164027637784307552716318515481724518532741014070576523654860028123444648726543434463586358076328861862385412143118625642628126672617763635717788356608737358238865854478487075717624743613147755325577155202642662650113374865061032648163018768724404227837151260534245414730837040272670625518524816844173752604713612421427581014835327884216357004103827372624624825607613685321838718783121783201546220877332618523484033418836504550354845557501255723257746365364533724770053004852604007145007653484371135700033413050162143608712741065021721558584332535787122020613285457067071122166270825871245825500252511451404363724313586561623662725341448326850605637645520652710734061103603553721504585707324281583008610265170617622430557127532416631412258328838374307302264678282601782132034871337644843401462742842107215876302171452753735780621218157840378626106652400582488562616865716354530113688531563273150642540215680704544160562010462168227847102043537372863606227863485764564280612335786655251320053243774704426146103767351675004061227771882487418563217101228257228474177206416048740843757752314642706176054186108442840481072688807888245121437337668018848605137653166518641703180318156612602033260572357615555665686231008127660607683820542312302436523202472348222103574847503136060448373050426708734310818546100012558051246608155643310633872255780650310786552541215201745381263325165137452788463576343674204721826037356042184745266584825467165112106006355167510788781105623465658773756883868012110284321513014454716525175616611768137427681534886023486205351442728858581666752868236430175106745042638321062083108321702340453041130612457481178582752050626158025384055005352376672458346427221748425807137606753806442562318172647335860725474830371583802351251766113664310376562367167407343086650862744558342510760512033105786441765808007204600605264376872847174351175438301566013163416683413510128707207468874177221405114514851318225231514632664730885425005816216567873025118726014288180357621523872378502177300555886517581515484033478831137167558052224442144782845268072021678508733840333135173515826820635274207417088856814547057513727206644577603710446785322314856685424538803253760515563520538716116405141054573465220348762101770782046356737660564646108a71710bb56c4a58168edb0c30f9aba6528629b1651ec7f3d4fe010447640c0c2463fc2632093713c10ef12918f6716bec6ac202b2dd43b2637a4bb8eecf09091a92fc1b9f1081128e4da97706698a51aec985b77fa207bbe267ea379fcc692a53efbd31773e886c3637a229ede8da0cdd2ae15ae92d780700c84ab8b6ec9c0b337c52bce50fa59d420fb4246e1e62264c0eae5d22aaec278fe76f27ee4f43165e6f28678b613bb2b482e36470569aaedf12b0f6a1e8d63761668120810a035fd8af1bec04bcece6cdb44a97176f4e1f5a8afbea4f4c08b6c42cdc167f933777f012d11bbdc6a6bf83e1c7caece6069181b7cd884f482fd02fea80cc499eccaa88b46847020e6154b30dd124fcb9acdcfc1b458b21f2dfbbb4192ace07e445dbc9024401ecaaa68bbc1fbb615be93cfbd2cc1c395fdc0f31e7054324f37e00506dfbeafcada9eef08e082f130396a22f0a1b82854b097fa713126ba0309bbdec3beee33042044d9fe6a20d72948e54421739e3b5df5f07dcdd343eb4947873e77e1d092357781f35e8771714a168897fe3c458d16621462f3d2130d661e83ca346bde9b68f238b264b5edbe0edfce0fe7ac1f6d51dafae7c15fdce3cf6abff710ce4cf52d7340c6c6c5fcbfe3adeb72987b53caf3c8462df45649028e57bd96fd918156a42df582f2d404004e4b4c589c2214937200b4e8afee6fb4a00eb88e4827d39abb8741fa6b2a65632f76bf3f242fd2455fb6ff3cd06d09b4548bbc0fdf4e3399d5926c62c2c962c708fa6a58a546a1c27d5a4f067f7cd0d6bbd4032493a68c6cfc5d050d779e9f389f8db5a522fb052d2967dcfc2f99a911ab8f7babf73944696b334a3f3dfeb250bbf6e79e95adda9f8a1678712d752f4a0f2028c6871bef429d9c6784c7739fa8cfec41acdb06496d8f7d013693dcb1000e8b8269a3ad0685d7e611f9d0e268d5c0bee1db5e0c103af2b416c6207e498a4b15a3f6fef22e1691ba30e296790414c4cd257501dd5ac4236d338e092b32170120ece4a9699fab32ba0447b32dd4957684793a77b53b7088545bce9d2351391c6f68d4f5b7afe553abe675c716b66b3733d20c87eb5e334829b0ba1efaaa6b909f9fc2d24517b38fca6f0ea0093583c0925b0627c5536ccb9891c801c2b5cba522a8f8f036d45b4022df9763186d34d2d137bd4d1d865bb5c49d7f5a73b2daac7299723a36c723367083e76d2afb0b74cf90eb9dbee3b39d756a69299ae2042f37b087bceed9ce935ffc25344e5d9eb9337a9ef17637a200567fe6c3e6baa5a69e8e340726d60ae730cf963cdfd0ad05745a145e9fe92d80546d7ab67602a09b777581a1c8c7de45a6abd1df2ae9f5489059c40ef605661c75b5d526ba9a928b41ffc93c36acbafef9ee13de5660790e44be35d8c797eb9831724c86a069bc4153e44ceea0746b04b9821b24cda4a98fc7a42c8ba35e7a191b937d4752619cedcb00d21cfb9ac21f2c933669ab073cf8f3b51b6d5791bc979c7b7bec9d49cfe66cecc937c5045b21cb6fc234c29fa963328b174c8537d204d79ccf2250cbaa5af3a8bb1014105178a8b98a4ef49e09bf837452d6d2aeabf589674c893bee8bbd01ec13417ccc95b7a07c6139b5ea1f069eb7fca0bf92f3744dbf1e24d469fa24767d2c0e7028ccd6aee3807a2d3459ae84e9e5516f50ca3c42669f70a61ca3427919e3d3c4f865176fc08c68fdd7a48efaaf92828c29af85f050b45f03511bc0bbaf555627a12c53550bbca665884239d3b68f419214fce906a47b036f3c5ddb300b1e58a545b71c74733af367d6de5519fd56775b84dbc99abbf3f135fde98052cab7b42825c3d76b5d3e0f6bb0c04ff8cf2fb3888f3350c4ba6027254e124d1e9871de84ac5289a465688c4bd68a2d187d461bbc4535f824ccba09dba5b7fe5ebf9f7f97a85e31d5898d13d770dcfd92fa3b7872ec42853760416aaef34c0ca96763d8b38694827248b062948a42821b841e623089709b55a9a26e7c985ce42b5f1db99136d057069d582e2af5ad2a18827c6ee2b5342d2a1daeaf1fb1e0220b95e850cc04f5806ffc11b304f842683ca1b65a02e76fd0a2320819b27e43e50d7f75f4cc3988c087fcf409dcc6bd92dc9b8c72a67890fdf4919a2a0e4bbf932c7806d25b5e728de08b26af413f0d74bc7cac88fda1b54b6c4fb584fda5d7d6a9e2f24c4548bf3f7a3f173845aad914a3a78baea5877841329694a3402600c5183a1e773010f7351fb0e57062d715daff483ef5e85965abd16973dffa3558ed9b50adf802c495a223a3a19b82c1cc1af654c2690e46fb629fb5e13a8dba83a176338a298057eb7fd674b43446d0bc50070a420ab426a1dda272148cc2d1253aa827298d6d402cfb1d89652e3993e42d52dda92f7a171eae4b652cb65d0f6d55b54d7cc5e2108e6d5c85dac4d5fd8e05e3ca6a060aa0af6bbe310f61cd874c16af5992609909543aed87019d72d07781cc8a42da9f0d680035a7703309e191a044031480d19b8a6a6cccff7ae2ad1804651fae4a2971c28d03863f5960f31dfe57831653f09a7bba185fd036dfe22c594d63342588422f1836f965150750c94f27b77085e49dc02e750275f6ee30eda4a0cc30725884f8b563b9f7dc7f6b3c27f46298f8aed120f634755d1ce1cd2e2e5e3ebae4bb5bc3527c6dd97deed0ffb644053ede8454bd55c3307a12da90ac6940361c310c081f13bedcf3edde165162e4e20b6e33201e3eb4e7d9307d5ae918f0015158a500e4e3ef914999ef073e34cae6a1c483b84372e29e600ecd1cb69115119bced399acfbd65dc3049be0377cb27a1670a76b8c162f7167b8ed59efae205bdb393374b8aa7d23010d475da30331f5d63ac67d2e1af8161cfea4260adaf702464837cea071aed36a217a029f59e7f38ba9e1c1ddcef91dc436f5f685aa0c2a1bf3f30eab6b6e2f7d2e4e43ed72fb8782ab5b7dd91657613081d04959fd045af83330ee67de3d388b7b20787a5768d1bdd982f5b7615986172387cbb65dc3d6ebb1f08f9e05ea69415383f51bdb25a21ed4f8dabcf3ba769630fe0a421dd644b1971f56709ba1bec4f69bdf336977122129ea64310792f7a48bbb12cddae504a179e3094964a8835b360ecaeeb01a834c383a1e726290bb2031242952feb5a4c3a02c9106a66905dd6bc931dc245dcc48995bc1be9f0264148d13a92c16fadea763bb62dc71454fdf1170dbd696c34c3aed4d20da0983c7acfbec2a87e0c45c2a1cd2445564b400105ccf9964eaa5b64cee57412b70c0eee991dc9e868f1be1c254dd006e814ed5412b5bc7eb5f60d3881a4d36d5dee5216db93f2258f42f96e21b58b547ff72f93dd3d5228c2c17771ed77fabcbbac14d2775c098a1cd66028a0e448bd33df3189b10d9d7520b0e3aca333b5f8551a3554cf140d2eefd6e30cc1e900b5a2906d11cb8ccb35fbceb3776573e86b9dccc6b8dac94959bf1969804cbd7990f664b517995093886d4606bb0" - }, - { - "seed": "06c016cb8566f5b81f8457f56175ae77dd05c35eb37b687eae89147dd7ed008d", - "pub": "cd136ba844ef8bd51aee2db3103524dba4aa971e5521d273dbfd2d69f0ef2cc3af64ca232e59c2e1f4ec56a8c2aa886f2d5266b72b1717e9f83eb353089ebd02636be7e2629d9128819e0e3b47c28f05ab0f06805bcca20fe0bf1ca4dd2daba5b9012d0d828a9f752074c5c40ba640237bf00e137dab33468b4073b7dfdb9bb3f512e092916f137c77fa23152b1c1c6c0e7204db7b0d0263401be8474a54f00b6e8bbc5e596addd254faa848224fa50551433bc786d063368acd6d412d94b34c5e6067651f0356a30caecac274ff0c1a87117f589c41e6c7d62822f0df036da4a646406cd44780c0ce6a6c960d7523241861a9afb5434f3c6a36f8c317fa267d0f1a25c1e4e5b62318d19c7df5f2af5a269205b638119d3479c692c611df51d2d4ca3e68306fa2c8564532aeab82f5ad8ebb33668028ab8cd97e8859efac229199b507995b1f96b3ac5683d00f3b44729a9710084b1069663552f64bcbc1eff043f53fb1a689c6ec82ff5a0fe1c91978c52140b048b4a656fd535143d9e970172b28ad4b2d41e28ef62618d7c6e7b9504de18f3f845a3ff291effc26564b2fa62e8d73788004e47899925b63712f211e707048ba59a9fbdb2079ba8c0e35ccdce7009bb57e425c734a9a2430b32647603293d6e769e6beb0448af3ad30b6309afac2ac80e1bb5285b233a87beee427a02d983aa02d6261e92c7771dd297ce29c1597481e4d8b2befe04915dcf2a2f2391424ba449bc7f741b2aa0e8653f92b8a03310ee8d79e060212dfbdde4d17bad0f78c84f21dde401b94318748994771d60c0c572c51fccf8bc6f45f5d5556a827e8ae043127d7f2c948b45ccb5d9be71aa6b02af82dc2702bcba3c8b970b0c6bde654cebc291eed77e1691852555e3c01e8f6f28537f1f20a9a175fdf01c333806011955b4dae11d9ec8dfa9277c77f03172754eed071be138d240785580f653ca8a21ce95c10152d9f82c1f50fde555496ef081ca858bf719ab9bd245847ec23b6cd76175f94d26a72bfd150ef152d7d5c975eadc946472f2dd7a8ea557f9a197cd420928593f1a971a95c99faf383b2786c3453892573f936fd4e58344e3577b062dde2f58413787759a861af09e94ad4ea06b37f818893093c76290ff0c96183412f0abd94217d830bc21827d0f6b18747a8a31812364a8fb9988cd10cac3bbb2a649c4d5614abc022143716ba5351acd138b2a06957f5ce978feb935933119e2fb0a8965d0ec3c14adbc82d37904e4afeec034cee4031a3ba4eb3b1fd6033b45b4c35a5d309ac256dd9dda40963c69be485653ea7edebb8cfa20b422aa14df1d5d91194490d8905740c8165f911d6a311c5ccd3b6e07cf46f0a9c57dbf4dc4a5382ad40460ceac5f6ea9ce7c79f8b7064239123a5563d2c33c1c122f5b221ccdacf9d577576213267d6af351f601b7d4c22b7956f363a42910d90a99cc77d4c858918007fe70865a6256c0a2c82821883627f2fe31798eb532d24317af4818bde315b82ae5acd3e9b468f2afb40eabee4e05891d4a09709a409b0db9a5a80f30906d99e9b67aeccfc8862b3e499b7cf7b77a2e79734b93724fdb0c35983dddef4b7476ba43ef8ccdd6e1e09b538e777e71bcf9ecfb6d26ed0846d58d2552bf2525242839d8db26f82d9c6404695e1aaad195d3d0f4e6f9795cca693554da5efa82b3c773a04a526d4086cd1aebbe609d55dd4a0cd49c2d5dbe590eb66b9b061639c524f01cceafb110361ae8c9d819220337f38b6512c68da333cc2325ebd47c0bbacc9ba651d7f60b6e7af1b8a04d3f64f4fa011ec5a15493a08f823ab7878684d9d6c1b23ccfd136eee2203f6e7585f97e36e4dbbe652b4184bf6e761475c0afffa4a92e0fb139bd8d736aebc10448fcd535598188b2ddb4d4dbf6d2662f769a9f55412b50d5abe76339fe3e162fdcf3501ad9182c250ab14ab6ed95666d757bae8486fc0633193ce3d3a3ec9bc8f29259ba6e8ac0f699037a172cbd5034df788c3b9114c9a605a1f19d63abe13db3f4255bd1c7205e9a352825ff340d794c70fe5a641bdb47573c5c884a575d768f6ac5049083387b348c77ba6d11f506ced5fb296d23899dc35e3c13eb984b1b8874c8a5c333720162e4eec1a43c77535a885c43db98baf15f0f07bf2c74858e3bed6ebeb210eeafbcb2d771f8815b567db720ecb17a1c675c1b014c365197d4ed8ad420d10f103d5069c83d0d2e39852ac777e0edf6681ef4a048b3ad6f4b6134b7150e8b29d1b1b0fb69112e99185e513a7a05e470a5384956e6196b2d8b1018f7c2f876acdc83763c390dc4a057073ebb972b89ffef171459652b00db20f0058fd0ccb8161fb0edbc881b84adba66ec0fc5826a4128f45bb1ed48b5f6d7cc8d8418c43b444f60e7c9d8c2c1f04a3d86516affa6e418a4660acb13390b44e7b17b7c63daf2460f4c00e9efcc531f2c1fd31e63336bce51b89bd1e6b867abea8eddb837d23b3b16fcca05cdd2924e2a35802f55bd8afbc8b96c50e55fac219fba35dd618f31c81acfeda2eec25350898046106815713bab9210d2a05a1b478170afe4b3778e051375d021831371b16402f9bf9e137d55e4fea29aa18c3af0760f6c9c647d472eea663b41fdf52f3832c8ce454e451b6e4da179dd5de087adce8de05f2a5d5961eccd6e362f76329a27ae77210d2330ec2af69e5898805c8402cc41f2edd9a2df411fb8fc7ef0c7b590a1d751223c6d770b8e180635c3a7ee8", - "priv": "cd136ba844ef8bd51aee2db3103524dba4aa971e5521d273dbfd2d69f0ef2cc396f5787d5293f0aa21c1ef4982d6d92b03578807ee3b173529e67cdbc4592c01fe4c422355c1791e28132ffe128ee7400a82dde9dc6c4a9a4446552457fc67014618934ec838799c91ec12872c9a7b41b56ae1b4f2d84e0a1c45e63613cf23b8143058026560631877225541240870755028612211601113257620730333171113133326014734054530822257254625481781338656606531637062386428216843125583177381435215743200728750178828264283858572338340174666155423803410245053881552033512106268217163576701115100151420758458254007203647278565678136022872018662578473315183258324430858168453864072542224242317055776525374818573571728183430228822052531150150563757546718458310706857665406856725636865568642212311532331480501803576035710033308324482566338724804414110081242517212343043345322274804530744840017770682328836674404578040172026160252354482574075878623707433412042010420315324686631430437621117246135145667012805637822015676733372011026256612787756404678851224687705061484330880505326284055581054124668286658020382004078761776361161527740048635207170416215413243527764483287008340567823406070005843544321560087377528537112747351413323761711545608265808303065815242428578631040654613162778428574137416806766647656885762514121044168162303486044752838523570078420858537671500835356333734424688301521706686448255386087425664222682810214243348461332478264228721251287155070578654184140476811887216103058536107683826460515064853244078875520430770825153374152041800752886860880705277852311445620558643661375387135831547560175412405304476660057527456133616354524282235243658540065376850627062681617338104541451788220635858838672766573864142370366455786746353087604586187606056712725063187712712448173850448611574436042456606878057101783345634527487132824126777640311332086444211084406665723663416404615362244124732217810466715618067505057624817681836341825188410360207772465666127650130242187521306645231253000028638486005737424660746138014572216528038511631376771854823406270830132667674806184712737536564845562848003181411682763004664515632264310472672641657307765353303431853146262328068560152456358001505514157483485470687546573587047517328521130710682881183360163073041784613833175275612544847536060656800117884142016825672787262425284372054865151236484576661230323038363486585601502573856284167732206132578258425346636431584100337878378274840833177664013564252244411184708104348334304276470112213147701405086214104113215886548778307185000683785205742088186133061432162674560501614305005453476872274532448663370472187828212621133266066680423603181222832354734806782474407505641561545776848377668885033003456617755578432240766407055388340333658406402462202510811201771475150833626185035600871018847510308042575856566110553231327801543061080331388054232227503550601672838252561463072541831582337012688050512015154818313653303778611543867346215811512217107581100031233816616052755553316276881007300046414722210544405685155425152663633145137786125875381612221375311321043307001662685838057425460185646272147556360106708043553528546214161058211015442016678886740618868527873410028761b9b238bada333c6e82897b4a54ab928d97c4a87932daeb797fa5d677e173b5bddb92434b1676ff7b965ab309ca58accbf0a6cfaa4b0c0c917677c9414fa1e9230be5f75cf5c63129c70c2046214904da3c43b4dfdec7562261c2856d1f86724673f89d790bb11b55623f5426106d2d5625cea933459a75dc1a8daa87d6000330112eeb17537734adb71b349190a2a70facb2f42ceda5681691b6ca9dba1b48a4aa72c1c7235becf0170b8cbea2833b25c064f320d8912fd8b5b30e4adf2cb9ab32bd6d2a63df5118b12c37460ff7e8f9d9830c51e36c7e725b1a8e1f52a94985bf1e5be49df468d46249f5c9b664a1be2ca6444f8873a76813078e4db1f05dff8a8a66759f94fc117ea2b6415ade0982b73c9bb8ec1116dab7670f46518cbb729cc8edfdf8dde4e7dcc960f15e4b417f655a5fe1b69a1af0dae73eff122a5e52907932cba3930322622b00e35766e0d5c55f1b7995f5729c857eb80f2f109c3393f7251d45af89d038a0f303a4c273a4fc38cad50d3badf909c4b8748c760d6688fcbddea1a1836fc133ee714874628e4611959291dcd686fb40693d398214b2c5ce4a0c88a2d9e6c1521f4fe425adc889b8e237e90db6d4de8899cfb85ef1b61a31ee0c68f6d59e1cbc52ea02b4fb66c05fae0b4e78a492b883a15806ec911f58ed3fe072e779df0251771fca6354b4972b21f5bea540875ee1a72d2d8a3a9a1707d6b0f562ce6d045c9d925f88a709be8c1933ae1ec9603f497a5013b4ba550c024c1db116783ff1053a6beca7393e4313f407316571c113004572f4a39346f2a67279218dfbf61bc7c7bd1052a3e38014f926496e5cc895c6412cbaa59771a01b5480027fe3431c6a09bd2db91f62c35b19f0a92451167516e041f49db672d99d71e1ec63b59a0bd8414eaff6c351c4f7fc9b73dfb508c1a3c198f9dbe0155f57e89ca8546845bfd8d4ba6953bd5ac46c7c652911583d2acd204b24b2a9850d6944a5b89a4fecaef23387bb845e5ed9630f72e3a54b2db5e6fb991aa77a4c2714ad041f6b88e5e013651488acb4f74e327fcc55ca05491e8919701d597d1510c5b47460b9163b736713df60db65efef3e022c326aba7d3a48abf958f630f15ec8ed234bc829d7bb4f1e7f4ff512627713205b6451804e3167fe01b99ba0badfb77c203046c750216852a4e7eaf44f97e24a5dc16245e738b5bc153b39f040488edb47609fa698ae5f8f86baa6b051be56063c9ec478acb41fb247a7349b9e8b1aa1b1e8f3351d2849ab1080e75beb8c68e4cda3f482c6f8fab0ab67a916dfd2a98f5f22473d55fe31508a73a14a1035161714fb6d813ef94e25d1ac9f8fbfa3641c45f5aa2083af05e31a458f8adba3a23e9c260d9eb3dd99ff4e6a5ac63a529d0f09bf70c9fc9e4092510655aac4f6c07bddb7b6bb4113e66f843c0826bceade05c0f06cf3e93959b9f0256e3ec12cd2b5d45527f1a99c2d51aeb9ff19e9b0c4b33ebc7f689127c5074a39d5cf78e7f5433279dc235749eb8a1242cf4534643137796dee5b74647087282241fd91f01613606517f852acb9b6e7ffd2b64db930f7459a47a4fb74ef9280768e7c427129bc6c488459c023b06ccc997fcab04bfc0a012bba03fcf13a38c225366b948c8874e5e958ac64e68df8ef055d071ae59adf52ed94e2f83eeb207d9630fe28fee8e78b41b1b46a1673e6eee92ffd61c9abf92c5507b183dcc30a239d3998d7bc2ed70e6a2024d18d26191f47ebffd7b5535a871a9071481725eda4312c59207b90188146f6f22d0c25ded8f0fbeec69c2f7438891451c366f1014f4410ea91491b77569eebb61c9bb500150f42c3586b37c39836d7caa54ce6cadd9880edef79eaab352131ab1a9a9e61732f74b20b5b438411ec812ebcf717a07cbe0fcc2c5d70bb46a741e0dd7e2b97297310ad0281cfd683565b40d7db04c47d34ecef6ff88965b4d858564533e3a6e6744e84ba84b250880feb8e88e748adb8b545aa0255ffc70574ce9acace6fa948d4307eea22f4b21711da0276a64365f00f23a15827d16dd172b33cd1500d59f6a093e787fb38ed23e3ad1f2cc5d2fa18043fbdee30108d1e9d2bcf53488bcbe02e7979db238b079e88d90175e922127a7c6cd6b72b87af752522ce2c0d6e766416cfb97930aaad9fce7f6be37b3bbd1e6d4f6759265974b5ab9f6bcc1bafe0f3d9810067e2f1abbddf421a21a22cda9ac3123bc479ff33dabfdd5c6f49e139fb05b0b7a5dd024b2725996fb0af19db7fb1462b7c551cc2a7debe3cfeb95170381a407849d0e0cc9e11089ec05e2e898eb2456044bef899f24629b311363521208b1eba36f8a619de49fc20ac474facb7ab2318491f72e26c7fb9e0c387da35dd7869d82134a9c61919c16790ed81f07fde26c56e5adc9e0803b260cd0b85391293debda809f61b781c79c252e03ea43026521bc435e47842d24b711cb5f75c6e12e2b10be53e09ebdb5759291f4887350ff986a16862debd9f262c8fbe71e2f106781f8dc94bd7e3f89de77893b3853146f1fc5265870f713557ce2e514b92ab652bae9e758f4adcb8399ef0bacd87231be1a84ffd58f4b6cca555efce7f70c6e18d1ce8380eec6dc8d34a41383b97a7b2694e8fbb09ae1ea9976cb1423418a9c13603aa67d167c7de85481ce58ef553d9c3781a795b6022c1c00b119256547091f4b5a334016ddea662540ab95882c608bf370513e1d041463afba71aa2086ea700061474fdeb1229a50e89bc1294caa0f892e93c2257925af7f18f9d28ea8d8419ad1121a6d8097e048c82fbd885ec3eb14e90dc59fb365c30c12c427cc9205e56cc1fe60cb6758e351440f4edeefcc35bdf6bcedf4a4e2c1c68a70ed0ffeaf5a03d4db22dedcee8da1f7b6b37046ec3279dc9573e128f51bfe42285d8e64ce98836d6c80f470c64048cbde71c10da83556803da4671323739fc4ba80278f2959d1c43e59105c3a398b8dc626fd58377373cebb033fe1211f05583ee5f4ae3283780c682056bc77c7855ac186c1703b8f5ca6bd50735c1c5369ec4e180bd5430a5e33108e1547914d3c0b7edb6ad734eb3022355f9327a23bfd535124aedd1cc9a36ba514e91785b36695795462f5c4ba58660313b1023b075812239a12320787c5c6721304651ba9f269f1e5656a875c8eea9e782eb912d52eb43f622a6d770f3201cdf2a5c20ce6a1d1945c5a93cc6c65a2a7627e42622b7954625d0cf8ec441c16b04df7602f52cad75bee96403bbbaea1b102a60d4aa3fcf4d5f8208a30e821ea585a130ea928e74bfcdc435bde8ae646841bfa7a535fea5fe89510b96b33c7a3002c442e311a45a1147f705e1e73962da730cacf5c94a10286efbd3a7cab12ac574acebb4df64253f387fbe4036f9330dc3670af3d5c5e5d39e9d527859ca6cb8cc47833bac8a07f80caf9db40d927cf6b2f88d4f8fe74e0dc4200854045b4e7beaa849d23a7fac82cc7de0fddabf825b720777a4fc2b4fd7bd65549f156a8ae" - }, - { - "seed": "af5a2ecf442af8c0371f89c499abc337021992f221c1d3a66b551dec917f1b1a", - "pub": "cd40501c8f6e1240fff9b675cbf9f802f93ca9016083a7702216c49f56fa13802b4aafe16a2bc444d2f77a328cf9839da78e4138842050af64ad2d071b941a5c525c66a5cb33c4061626386eb5bd8586a4a7d3598bcfa9367d58bf650006f07754f6820d7b43b312e6a4b7a3c19e870d34d80372f54bc43eb93bf58ab87ade1addb21f3dbb7ce2c3a6a39a89d3e1ea741a6c74d8ace6bf37e97578da064195161d174602ae8eab65c8de1d33896f3fa4a3181a5d6e75b5b718d3d8e36f39c54361fde078e2286759a322ba97afd217b72517b3f1397ce10960726700173783865ac596b47b6b8bbdb8d6b64d4cf8cb7acd5c58da9ad194d15e849d96cc51268c288eaa6133b8567607215778012fe046bafcd663d2fdb47101c02326a475c2dc8dfbab87790a11ce0b672f41e102980e7039e07b52267dc7b7f46aa07cdb42b65bf9e7580c16c05e50ad305cb0e4d68ebd4b92980ebc978e67cc115422391489e1c067bdf627f78f512c77da348bf38bcfb89ca9053317d3c7b3cd1fbfc2793a367d367ef412454863b00c6782eb813a59b0e46f4d653f2711e225807d59d5398a12d57653193b951b25aed9811a983734c5521f068c1dbe1e008088a81c88a7fde81d8a44a219c987cecf76e1a1849443e17f07c2b56a6cdc36ff4d9f30f4aea525853532710e21ec5dc16c24d1276c11b36c328a5d4af570d6c9dc7820258a71e1d5ee4b0548b49aec9c21ccb5c2fadc7c9bad23d8dc8b746ffb82cd78e327bea707968c82fff2db878ac9810015a9d88493dd6fee55a5fb18a35b595d7a4833edc7114ed47dd87d5cd236533b60d732cf6a24d27ed0b68dc9136b276ceb4fc918a87c1b410cef13d062763c54735c267694d07e6ba17d66f88ca7a3b082492ba8f4affaa66945f7b5ab62bc5777c443db0e7f84f2e6756087a5634ea81db361a78409386f569f898fd257c9307c9fcabc5ba0e391a012da3e65101492a7fa9d5cada36f0d613c1ca3c1bb57e9f6165c06934ec1859d13a1c3888178087106c6f4f1fc46a10fd4a9f1e5d83165c97b7d1d71a9e09b1d8101058739499342fa5291112409b93953b989fa7e68b733aacf0927efd4302572052cf508d3fd9aa1effe53b4d57b22ca8e9ed9f0c06102f47ba853ad5e4e01501b6e77e31f2010f7813f339f01bd0f43c3f300b15d36ad32cfd7afe8c786185ac8773e0f30a8cea310d24b7cd068872fab88120a24448637182f477ae10473bd3653fe453002cbae148af0c6c4dd1034ad15843ad2a83795090b1c738df100ba32199d0cc01d3ff7844c524973b652156257bedc07a533c0f1083827b24c3d77df19f07249c8523f7dd350e75ef3509b99b77adff5cddbba4fdff0bc89a3f2ad2c2ee8137b0ef847b4b879edd39e299cc205e5e79995d80dc8d67efb93ae3d6318c2ff67f8c31eb39818abd6b3fa0f2c6d6646e9795d5727458ea5918ffa9a62e7528028403ee1f34213588411e691672dc1989ee929f69ffc1a87eb72219577e24d3f31e8013cacf03f8600490c84cf2348e10d4b1da72573a9f4ad9156b3ffaf41b104fed8204e64a51353f47904b42dbc4311520e3951a45e2c1373f206d558e0aa127c400cded08d087734e52fad8366d786622a62a617a3a6ce792618837c635f60c45608110f191912d3584ff51d84c35340b9b5b3b9c94d6234e17e7b3a0fc76b48b34db6409b0353b4245e21a15253d03ee89fc1c25da0ab260ecf9994fa14ee59ee88048c12ceaf3e28d1e0208bc09f4e173fdcf0cb4d985913d093b6a37a3b1af4989948b979446e89d24b121f4ee30a3bd9611d698b1b4b9f652724bc80b2aab623727574485377c20e9621f3f5beaba3943b61d4938238509a327ec910c4c91ddbf0b4a648b1f621dea766217bd65ad8a628a39f28071b741cb1276620a2c55d975b1c2c56f6e81bb57b284ad1d6985a204478ff3a4e849f5b0fee7b428c058d1d393c90f436d772fc7b8f9b9dcf2052e275f917e888fcb7e2916d48fc51e93af143ccf0be2abbc05bf10577d769ac2706177d5919f5af6de12e99b3d9f09952230b036e3bef89b20b235b9e250a02d4cdb9d14551ecdd5c5b0669ee409ee6654a9223f24c8a1fc4be88c993f8bf25d783c79087bc66c00ec0664f33051b18bc2873b997b15a38a2c7e8b904c00170b5e9874da8f50b76490d0f1649134107bd2acd3717b5d5474b49bde361ded36eb52a0132bcf5edafc82ad33618b77f3a382bc32624d39a6732522e4ccc05bfec4b8a0af5ac143c3a403bd5f14bfa86a71a85edf5eeffbd081c99c221355d5a1657a45370c5815ed7799be3308a774746878309180da20792943acd1d30137db52dc46e39563e1370c4eb09577ff3d58d1db81de0c7241dd1ab6254362fde4850719d5b57b237882caefda260ce190536aeed81503f2d7713d62c8e6dcc668ef5e8ef6da38bd71c2e0e2b93d66e1406a8930d36376832a1621b1ba35a7cd1f572ae2a795fab0787abc98ea6bd6089d9f02ec071205b603f988bca2e327d70259f08c6d57db635b740bdee9db47658426aca91a2a40ec65fe7171b1d8053f05883ec08c8484e599b2ef851c330471f78c0a8819154be4770401b7a309acec2c412f3dab3c89eae5db44b9d4aff661d47aaef05e63ddc8c4ad2bcd6a7f32c6685d69d97d28db01eda78b988b974d275ca566ed69addf84f34e5a7cd4e57a95e19e73acbdce88c33242a932f2945f2096ed0688d31", - "priv": "cd40501c8f6e1240fff9b675cbf9f802f93ca9016083a7702216c49f56fa138013c48b3cec2477128aa4f1138d64c065e4ae6f90825b8883a318e3c0e57d79608872d8b10c822daa41cff163bd1bdbf8f00e9422bab08e519a346a00559fe33c1937b0006e751d8e89206d6bc60cf86c989cedc6a650a9d8cdd7a885a5d5959750448826460188004101125111186074620576284254126602486514650254327504054426658404637850147516850678005764401755744635128034716451535421171000447534622142286762007017285656210134675821180311780513280388413616213558436053280311820410525136513060540160781021887535516157262345448444784701867043127643363865707424667300015652134858161472800247384008538765723005036486454028675180110070100585227018422187630788540325626225188813123884672141516606825703365081484622675274186476437010486026151361553084613341471802783747425386776481227074016862284216366468674776440845680570115565427708841053204705545428355530152603721866522350763826432546480520011000217246455705043270634768453003815312660206530127032003278361545060180436455308127725487262482742654007210440273753502818225888755041314584755808333558051776484568406766162183053205233717482617042441680463342553134108652603646478047082474478071810434283471763142724425102083470712525401031116854048436637142716444771867644085821750556353854203622388308758477100636263240477537720385175337344211355475034614513544055425640506651668811324364614815740531827808364780478544043850587041437810503082400163542252323515405157863646838612144458502587220415731546766633753238104428464045120204231781335071761541014428403711427277077374826708330641275013578628428874500743644104623670603744818368054481625408140001614207775166058635432827321472400672317435015252346535680281888151477005612260638815080663703827487130616081186003343810854681567106141615804734621383114175553858354054073406806336125653830065280187374320341007765836446711861021424842660758755784704122132480132102238862510143518701447661211335031546207621450714706100313847443215510114355878185523877811720703570726544284774414545134241257007847220580113313158613736252646822524660278672558356438724635513883380417860673588850524465417657131258443717224832306011153434405086734832734238855846814657087130365072151474425107710001447436647300443625157617824024324281003277361345864124855547568664642638575406011371083735120870107051813268152180133151542028272641804564120630702784343172240455064040414206576102854172281178857284212558163858228783344551685467747877225614622512371447002823523287806683488140720812213887102060221860281611143315388888484862187875060500504384547208612234821708336400356848478172006063423822373324570772060541305847652773286164648028265165301157086073527525123782386608802465083320180637434353766062137470236812473248565115246843013483416800782261353501433487770254236463403451508568564101825531344410267156466015063128101007831428421211188415154723111285433565758007356644774022346717041065367152658860424264228021125381712078461548403462250318848437146704741046774408631383441511034835475844544150855632038827538235253151753601010467407471214815105021732547307206305612530887784636307521185fef35b7e37d1212c06ad85c4ab401622c11d1dcb7ba0a9f7552b03d3f263d4a66a0986f2eec297734a9d60561fb3c8129c37a3ba600c75f4365911f47d8de507165f9c6c79db19992779f091115be1569f4237446174c11b193532c716bfd2ab84bae3852acec911ddd3c0895040bfd0587f898b70e09e71e1c8cf9bbe4580f17ab55ccef554ed6745f46455862b00eac4f3ca7eb66fbcae117d94003c1df2a43cb4bd00a4cbbfd252b0b6956a61893f022f0709000abf488d366a1ff501c32e1f3eb787728672ace02a5f6d2a40d734592a8bbcf5ec8111db6df677a6d0e01006eb862ff074377799c7560e983feb4c382f89dedaf21d5b2a39eafabdea4c3693b63d0d1b121886e5c3edbc109fc0d412a548567cf467ef10830098efd8a010038236b05deb89d1d36664fda3476c5eb93d71be938250d307e5d9b42dd6ef72188a2fe5b408518dce4a36ec95c4c1e23e73827dbf9aefcb93c8b5df3d281eeb9bbfec3b29c29af773433f3dd11ecd5cc94c0e9b58f96315bb12dc9c7f43fd1a148f1f95bf7f10ecdca26ec30515249869e2c73b976499e14628090203fcdeebf7ed6b91f6bc99a8b346421e991bc5b2e938d73d04b93413b870dfd517e6da6eb8a94eac931b83a68bb40482ad982abd87ddf0f32eee6699fbf7679205006b6d103432c9ac032fb18ac75a1aed57f37e28f3188d143340666677a1f9f6f5f7ffbf777d593bbbe243999f24172d2f74305f082de10517528c0de33f4df1d4ce360ebbdc1fe3efbaac2e2e573d2aae42f0535df07b6a2808a5960a911d6f04b87b15731bf08a394df18a7e2a9f9738305dac46c5c0b8054f8b06e9c4f846a0e49b8d194ddacfe9478d0d08074b7c27e5fb13e9a8b6a7ac3c85717e39870825aaa1853de322a904455a9c42da9d8d6c0254c943e5978899c6cd910e7ffa2f666df2864cf0cf668ae1ca8b062abe1da95132721921abe689da865dd04ebc092bf2aa2fff57da38dde2fd9df29e48d2049c61d7e506d9e5b0026900b80a9559fc6745a794f5264794eaa738a56829350ea9ade450c2786cc6d51d74a8f8c8fa724b4458cbd35c71d02ff49e09997d6cf57e3e0b3ea3edbad9aa594d69355a501b09873b433997fb9fb03edf9acef14486c491d4543b6d22c20f5b82dcb757aa7ce5a58b6644f45db334622fae70d4bb957cf1365bf1df8457ac1a6116d50179b9f4de05367b0313463982aa2177f9e66986ec007a6efbbcbf6a7dbbda21536246ee27a125c40f42399a56935ab1d52cd64b66d79dbf26af291eee29fb7d2fe6b07dfc2768b62756671aff32bf43ac85a36e62bde7f8364ffac0bb74e43b4620c18e308c6694ee8f6656ecf25157be214c498dd7eec3ce6c8cdec15f90da71bfdaf7e35ff79c10cf28bd2b4e6cc5b006d8892bb49f3a1af40ed845af81f7ee9d26d6199dd628f0a1a0965760fe30e6c3b00c3add14c6484664d640933abeedf8afd38e4bac598353ed16cf66abe9a27156a16743036d0fdada91563013cb4577f691075fd5827796531d3c3b4219e904c08418f3b05d699550f9b6a42a2274a07d3bb00a1c127869ba20da27b494904737ea8d06c75c26c74e745680bbf20713cf7df7f800cb9393a6ea984ab452d8472aa18fb9b77e1ea98e2b949e78e7dd5b136db996fe57493669a063275131a7c1207e7110e4620569c51b5da00e6abfc839f3a301b65f6ee92ea148f631feccdabb60e6c64a3d1a03ad1ff48f540d0212e6f49c283e19b805040ff74ef6982fae0fb8bc3b4bc123405ec37df7a76a7f90522017702dc629a4d4cdc38eec96b786b7e1c7a8bd559d28ca2782618f771a02d6ae77c64b0340f1205f2ad0ab202aef7ba2908def8fbe78848aaf2a7ff551fa952d0bc58581a9c95c7a2bfab8da745de41a694425beb6df3652deb5325d0a42e5f2795baeef5b76261a1dd5c836843b50bff75f53cbe0094af351990e3b3aec21a7eb5341eb652ef5ea8d8e6db9ea862e1807531ecd0c0be38a51282b8fc579d8fcbac82e49691fad4b45364f280d7bad3902e745a16a94929870de881207dbf076691a7ae81a66ba6ced9fb349a466935bb34028ef6c30a03c0e68ab4c39c129ffa85379152013245388984808c56185c779510ed716006f4b014778a5706d4b8d02496ef7c47d3caf14c980bdd48be3d37afe25be1b6d18e131d88fc1043aecb1cac973707f61ca8610a107793c796f87f40f67ad15a6b2e84ce6c8e6c58ea2113ffba3ee77d357322aeeea80be8e6b2fd7f52c8689aaebec7203c56f6ddde1b2e29aa4cc6034a9f2dd07da138b21285f075fe2ffc8329f5e8be9d82f4762cbb746cc7f327fd21720b74fd3dac57b8786299f49c6c602c7956adf6bf661594cc5e90f4da73ad1305fb1b554dd4da00aed39bf0ee6ffadb87f427095e10ebb336b7036fa99ffc21cda513ac77db20998dcc3156ab73991a158e9136a688b70c85048f09ec38b6691fc708b53b9b6e520ac55a48f7d50f3c863eeee841d984c75444105937ffd6b3adb67b48e7342323856c636de826209fa66411ac5605ec7f7f255fbf88b236ab77b2763f25155265411c74271b5b8a5b835a019cff0bc55233ef268aab76b4e9859538e90e818e6f660cdc4ae93906da2a5e80df4b1d5e0ff92243be91418d5e3fdce6b50d2727948d2559994c2c40a5fc27cddc97d1ea18194dd3974325e8650de63db2977b824d7354f5c90e91a2950e69f4f628535d2c7bc994fa6f175b31b7edb3cae4d259bf6477eeceead8178d6c67d44d6c4de1ec3e5c09ae82b40c65e181f0a70f10199322a7cb53ff2badf4fd53733e5760b2770ac53ec62e25a9b82c3b14da51f746d6ae4cf7713ae33add9adc97dde11552ae2d9a75455f97ceef197daf5f83dad6b96e22773e4b0a1ee2c4916e9c07c0931ddbdbb251f3135c979ac8b81bc76aa46bf932ebbeae2303e35e723b7c90c48b61811b210001564d4b9a58d18c46e58b33d70251699500854bda27c1f58df5ff692b138c1e8a42504d83369beef19cf466dc78a9fb69fdd283bed6e70e89693a083e577f628c099ae38065d38fc2fa9ce5af0289ad653a3c4658cd7a65784f9935ca396451990cc56064933d7a52a5a047bf87c551a842f5bfc0d29f21da27c40771b86c310b7345b5a9e29f99960e795500947958abc2a22a166afcf6f60a4564e5b00e3955318af13e10f79268992d58a73c3c17d739b2b1f3abeeb1edc560c2e25c846c31bb644d4e3f24a07e7fb23506db4d8fbdbfcff61feb010a02c004f33b39d99eb602035b190950e5f0aff31db5b603b1d578e054af0cdc324e2d4ac1753ee363ac120bb50b70fca0e7a9a30569a701c7723cee90b3e25299d35ec97ee34a8794d730ba79f249d7366bea5b6afec2b3071343198b3077a3290957f89da865c1013d80a3b1ce9a09b282f989218df94f15f675a65dab79840efe887ac9a15cc16f1c075e6c7941812a77cc8938bc46fd8621dcf20310fee350ebf4c07dfe758" - }, - { - "seed": "d85d7c2928288cd0b90d7269619f8d8b4eb3541f7e084cde0e39ceffece9af80", - "pub": "c105520234769bc75fd0f4acd281dcb4b43e2406041e50babc04eca333da1b18af77a88253c8892f6ebfece56f0433c3e0d5500cb944bdcf554eefffcdf172ce264916f22b21d87ff3ecb966f0ba2d34a36c726537abfbe2eaf279d740b4afc1d4af798ee5212c7b6ad63e0b14a10ad15c405f2c159cd98fb38df453448473cb86634080f983b1309134427b95c48ce4d80933a4e8c20969ae50d31b087c3af9e2e5f189b5e92221c7a699b2874ba12319fd27f1a96bfcb603752c24b89e02ea863c80e5d5b906f5ad17f8812fc928bfb27c168d87348287c6112bf1c48569c719c20586bd825fc4c8cc214c8b8acebe8c305255b078035919d22683a3cfca6cc1b02ea3327da2483791ebcac9f1884ca45f16fc2086169856819ac7f73ee4bf3d1fb334ab587942021face990ac71ec9c938ad8f9da7873bb98c195fa477e6d66815264068b2267800e7036e955dfca260102d9dd90849a603f2504cc142e3c0fe2744bbf908674370fef10374554d090c039e78558f178412f65c59336e8d5351ad74d4beb2e82c1423ab672b58e9d27b3db4a39ca733bc6f556ad171b5302a9d93a194296ae78f4b3591d85ccfa3e75bdc7d59a080cc9c42004c3dfaa70492f2019213b72837234783a11f1cb88d6a0e35c1ce3d4b8aad793fb0e16f10b32db641df8452583c8059270faa562a0a94d250304fa03f6c445ec45f6f5ee7e1ca89881108503fe71182466833fd09e6229ac09cf285e86d2f755ddd58e6e0b4250898abde89c802b7f1d8960d74fb9912d156b81a4e9c9d3dc052dca9045e0b666a85ad6f334e4ee090014c3b2d23e902757dbf78fc382aedc9f2ea122a582ca90907c1bb3987ac70e353fd45a3f819931e53fa1abb705f2d143065ce7be38ab8144dfe1248b9b69c2367d377be5588dacbe8b572540a0e6585efc801e4b03786aad9592064459dfccc3583132db9a8a500a87684981b121b6635d5df056539dfb063baf1b3486a4cf80af43e828b8c1a1b41c9822475048c91281d206e056bdc06b1b8865ed92fa5286f6bbc00014a4f3f28a2c47a609aa667174bd0ec308876f0043193f68e3067279ae809cae4df6029ce44f836ad611b27dc35da4295f1126903e681f5a97239f08a2594768a91d01374c403243283ea763f4d23c530cc383a6e532d70f9b02c64847394c44285c20591ddc84ea24581da5d98fb248bfae3e66e20233893f89d50320e74473a1045e0c2a540f0797456c6c121b3d2f5bb94809c0febe8ffab8d9fec020ed5979685b9191bf509592f1c1d98d3eaafb0fc551aebcd53daaef10b997a46c593c0bcb3605f58b8847aa9dca8a04f3cd980825f8b61055253c4de89d225f7907d9d0d3e9d5ba1e3ab13c3e3ad89ba579b28f7d11ff0c757dbb8c1653c1c28f39649cb19ad2cad524ffbc21fbbe58a4cfc367bca0863175567bfa73a681948c462aa0d7146307988e3903c9971a81beabbef66ad382b69ea297b80422b480f0872cc00bab0faccba788941d4374fdfdd56419b6031a1db23a5a4a7bb0b363366ac5df5a75a72bd9dd57069074e3aade3d154add4743225564babe2e68b1e0028392e23a3a4b8e1adebf4661f64191dc9f46da8fcd5b769c06b8349c1c25090a29ea254d9cb9537662d339108d5b8c7d5d2b81524abdca3b2c5f18eb38f2751062cb30fad5886d287e968ce885ac1631380db84a304c5abd351f78261e2a4f42a9a175b87752485c984936831a7b8012746fbddcfbfa2bdc0db4fcd0b79f7e652e5d402aa7b640eeaf8d607ab02021dbd0920ee6188ace856eb0298f6c2ddefc46b4d5a38d4b8ab9ef29065499a0a83d5f319c634e281f54c7519235aef1db1963d436e0173ca7a7fae1b54303067d95d33ea9a25a94a490c55634cf4628061a864fa25e6e22e2e6fd7d733b0d1996c4e47190bbaf6e4578a81b7a1704cfa07951f61d8023ab3f1c5e173785f974d53acf35b3c66a99634d2dc3a8c404247a51134d41a2161c4a3d0e4251b0579a9fdf7b3a7fed59637bd9f8a68ac98bd5b1009baf290ef5117d6faf7c8dd87bfc21fa226a9b0126f35be6694d507695fddbc48528c104dfb00662de32e79e0c132ff9c08fb5ee336c98a93f7115171b6c2b3269e3af5690241a66645e96799abb45ba96ca3f558e293681a28066504f3b70943c99a465925906fa7cf3b820988db0356aeec8c9132ba78d212a33576524812ce85dca2817b3364d68670ee07329980cda3e39d88a8ed2199d55f5558cf7b817739e618d9405be4b8427a3793d8ddf359f19a9ff09b2e2bec22ca7db34f2b22d88df8cc728f5dfd167294cd22b144788c97ccb5d93361e6b74b072191bdff77a6fa78f3220a47924a3d04948ffeb146838006f58239496e4eaf29c66adfce9724090facbde3951c053f42f34f764ec61a1d3a8a113ce2d5209a071bea934101a571797f5c1c0194b9c1fc3b6599ac9c4790d83f55bc1875347f3607bafafc4df2701dc07b68030a693be88df3c0372707318402801bb20ce414795d7f250053d0ac39c75fb68ef64eb419ff859d89a3c86c879cfece9bae38941f2307c920f1ae48c3df72487aae2bc63fbc20f165dd1c22091392d43eabae0a6c4fdb3824e48548310526ad7a74e4ee6d73beebf13edb38a59d7232e14a3778df9de871596c32f0546a16fba37c16295b69ee997641791c7f3d5777f09af55ea3f65314d27785810371470fa5617cf2ae06818318a0277474984", - "priv": "c105520234769bc75fd0f4acd281dcb4b43e2406041e50babc04eca333da1b18ef9bc3e4ca859e29c9ae87d9f6abcaa84a84b20de0894f37538e4133f557be79c5075909bbde7f5d579760fc0e58ab046e437de6407cfed9ce5dd4d5e29ab04daa70eb9ebb4d9f8af32e0f7827f8d21bf738584c05d72bf4849f86a939718e8758445758814405066377236336162422838141762541276638856732360636423606651537874070450512230825442745831855684586351301333083575603024146601761737864228634768611208800655885828450737877205363001110217403351766632673281486707612045613182023667776367266083085712334830625737734852167672546845358411430645183583205065515383430563752021515024067500252010305132523852061423631568837802262668835487215855713274656266553465801348565243281764238745587354847434233833785336228853521530475450885388486887835421722800658106572655224626170632788231534531055663633012723460285353506035756252730815271414513036013604238484541566535734773380388840006280582113173886805271424366177715072681663764401431567346132851240273782202733172167802164088384310178216148840587511022757608251252064470305511284744230376254058476377274278086212488134263172827505611528825772601057638282760062084248067366371506358270582646651731160837361726605566053122200085235782558202084671262280830376814326676177807216075382173587246317674115285874745625236467814027788077336464042438520155042207346565724471747218387263118251375556767004053380182005875423780068363181661642242542646383023783342543587832154174778867365514222838388050642140134550860437148533084783344668707368431437015074670186306765104170870588047846213541524414736145150241215537864250374007845472700883417116237873657100750277242403235832704882353311545437405684075044150771571660005121055388384687305874147352600277663431646864700661301872840663534130204184605151861678802848543043027112104621511332255801120370470314425616558471472110733484223773623516535806637808681554467580118184582804154876801541184062762533732181015884585322680581165844687268617606655544276240638067611886232388527868508066182130307666322465628720528384531681113858304217150642806020144620080026852272610816183175145551704480131107232330465767126775852210875576883641346622737681600741174706303221251408630641587163003138713755442054141327080413822046600263640713611635310468722133311135012064031401143771510032260820885658416866680820730365314128654311255766615845301470057467310803472744450477206372254274621747370402131043815278774511034112778031445315048801015187323248127122555821044371482802710874843188101116516365815731456515676384256760350158471615247286366525363544813275860301445876074135438836883327838320860533654243487313251171802278742026065607171267878685588702652134688634745721733478005842454053488684540346456381110877324404284677613573082782065301706732632677347535583500558363725728148105342685468251370277036362661674818553152823343661441735136803538852043417412770322111347850373120404206488162576682561408525683855506861223536747512321018852123356208573123754682321451266335483743432708612575374514747037003725505244127842514108713422352781075135017606254307364886354437140385584416227381884e738df38784d80afe74520cbe851f26e4100d19105eb33b399d0f6165349133ce404e2030f5cac75974179afabd7e4d86fde3830b6b1be3e413814a2a06de211380dc4fca05b008125d64a4443ff3663725bc63345e388cfedc27f2ee4c8f8085870c29e360b3a695c984a30c63511e479aba406a782a2eeffb4b6d787f867c45d1f6ebed522c852ae8fa4a561906b019a62e654dea793ea955c6da7ecf03261947eef8fba2c47bfd27a3314b46fa227d0d2798cdc22befac39cd11bf0db030a68a9cb8c33e7890bca2af77cfed475871fa7617e98c86a5ff711b1a4f6a68d2d29423ab4a9c7c9844f93e90f3118dd81198708a1af8017b7b8178ee2117afe34a2847a97592b9ba517a1a54fe7cf4ba360b62a1daea0fa6acccc1e588c46129f8f0be8123c8215dca2091e8227746f62c7fbd2e0c4eef88497c185cc912436f45a64724175eee4fec4605b792e336e3d457bf1891c79c9737153c9339544d59be170fc0508d96002a7c70e2a2e826f59eb661ee644f1fdc88469d851a9a5114787ea6c29a3c583a3f15d32fc93e0fd8d725d2257b8151cc001e681a51e05e26bd4fb60e39e2edc1f6ca39e7e55f8fe1b24cb959b44a55268932e7dc18b5d80e97182ae3e1042bcc32cb57fa5648dd6c8053af7fb0cd6fba70bee596d9141ac92d626fe36186772d75537bd37ff20bf97881ddb831e9b3d1ccfe9bfa5b8e5a52dd3703e5e11459c17db76dc12bfa716458e1f0245c9b177e341e3fc113ae2b827544baabba5ddefe017cb3098ba6448ad135fb0af73b42090fbc3968e9802bbbe9c6162bce1f76cd5516fd323b415ecf937e97ca231a64b7e587e33402947a9d51cff658fb63b529fafce3a6a5cccd13dbc3a24c08f6ed0d2b218571340c716c4130925d9d0307645633cfc52e6c38fc41215d367f414c5c123b1aa87dee2d91e5980be6b2d1fc9f46aabdecd0a7c189803e287cdeed22c683abf3d4a9e1925b2561bd880cdb1b92e2a1c6aa4c33ea39a06fe4f358b73a87e935713745fb8632cb52da1e46dc009bed11fbadb6b917026134529a72340b2bffec7184b0ee9e5ce7558af7eed869c884448dc3f7fe694f1529ec766ea9b5e212fa217ab0d6ca1f6f99b4dbc7f62decace5ff9f9197ea29cb99d3acd62ad709adb2399cab425ad994da40ca7be048bba952e7e0c9e41eebed32e0a4de84deecfcdccac70f270fea91bd399d24a9e0ea318888c3d059c7230f5e8bcb616ef8d372f34345f478250512e313a828143b4596892f19818dad08ba3ce4f8a57fb343ee0b7a750fb19f7c598609b6eb01ec54c571a907411d72d5e04ebe8fa14574622764d7b1c087fec221f1aba307f8e9316db1d5e843526657639e60fbb7a8a1707656f1e6ffd50d0a2b6c900462a2a93235151b6d3eb32f75798147d69cb2d55d48c48f68da83b578a8dcae89c480520df326cde6c92367d373e473fbffdc81054e8bdc470690b1df0935a77f004231476ff2d6a47db802593af5cd584eca26aef41e6d8c94c552481790f6ebd50d48c142f575e3b5cb5b3b9c01ee818bbabdc9324e5e88a842ad90743771e4b542d468f7623ef77bc0f330a71ce2f5f093e3ee3b4f0dfaa56088ddf128ae9953b0a5aa1264dfcaf098e43c77d5a2c4baea68cb34507bab46c516b06f7dd0e9faec5baef6000ff918e53d15e4d8fe7828720f8608bf2dd2bdde7062f4ed9da5c547ee0dc2b1f4b9035e1643d5a9868ed871df630a007e1ab95b8a2d42ecb35c6059e162b7e2a04cae5bf1911c1d01508b96413e4dcba4ca62bef8ae8613434621ead3a9c5ea09f170ec59f7e276b669e4e133db5a3e49ee89c98d3223ddc2fd36c2f14c03d51300991d3eb9ae3e432c6119ae978302be54052bc4871eebf247a79ef131e39ade8020c61bb07d065672fc3cd14f91df7b3d48340456ea9fc42c3d5c0aafdd3f04af870629698e9ad9f5cd9ec8f3086b937a6dec7619ae58b32295037da9dea0daf9efd6867dc2e045bb8c38cea5a9e2f32e1129d29fa3c44590f0d25d84b851760edbe3ebdf02263b5b1ab4a3556ca3a66483a2d415f261e03ce40620bada221305cb7e811eaf8feab983ef9463f41d23da60b7d737677f7aad8831c81befae0088322c9481b841e0268fe919397b2c48bc6d4828b375675eeb0bd41cbe839c9225d92da70958df89269316f263100671fca80218ec06ba6be4df202ae0ab204c2e3c06cbd25f160ec690faae53d977752713de3c6140f828ae24e1157bc6f5552e306b08ce3b3445694a7cdffd491ac58a2de5c0544369b9bf6fefd1010633bd19691935ba21e31a2bde9e11ec2abd52ee99ef84e792ce7d5756925a58adcd522932e8c3df4a7bdc1e6d45f0d32907082ddbbf5fa15d1ab759f6b1e5622592d6f867f0e680672434341a653c9b435551ab55a1990061a8e4ff56700e76fc3fd715fa2cda54d5dce687ca17ed530b13f8e100306ab9a5dfd3655c3359ba4c20933632ca2a00004d0b8a6c4167b46949355c1379fa6c34f5d7a2ac4d3c3357c3b1c14d7d7d66b520c80a39ca5494f2b32f9f94063b1f6bb20cbddda4bc56f6599c343035492299d28d0889d3d794424c224dfe4bf48d414151662942d8269879dcaee5e924819985cc88f49f1d9bba5829579e823f0b95ba75bee15a828ef9b77ac2d08352477ad23d8edd2a0bf64f2ee58083b2ebcdef0dff4adc99c2a809786dc4e1e12e6cb6a6ba15589cc627a11c784a944d255b8ea82d48089451fa1de1e8fdce437e97f8ebe4d3418cd830705d1b134038d95b8af89e0b851364c8a75874fb98e1914783556d1a81d767e5a346a7eff827392a0ca0680a48bafe20394fe98ab290374776d1cd314127164338c2dc78ff219ef6db244bb73cfdb3a2272daba26016a6a82be03a50e970caf008326a51976d717c121b22d2196582dde1ce8f226d53bc95572de85b5590806af84589b7d608e6485ae2df98538074a56d5b15406dc95c08dbbc27fbf6534668d77386edf9a079f79a6bea49791e55e53391b2d6a21a394ba1fa6fa9955a500d702624c8a26992cc1454c5118814f959a3bce54e308353c2252106a4679635a1692e160eb5c5c028ef93538d082d77946db74c0175fb07cc7d2e98c77e674562dcf316c7fe27db9b95cdd3aa13857ccd3107ce654ec46b39143a411d4a30ac43cc3203e8c1702cf30fc879d1647c565a0e3f204d87cbd8a3dd7eae4d3339023b995b85204e8eee81106b8a51f00c8d8178dafa786baf1f4d236784a9c9b3c02976605a820b9615d1be26e8f43421e49ab558b07b4a05353571cd088b8cdf1f7077209486b9a3176f5c934a5a3eb79d2e60fcb687df8be0325681bc48aba956d006bc0022d6df92b14456087db752c4fa8dc5d3a7ed18ec9a5678f43ac498d1ba6c68f1e4beecaaa3dad0b6d5bd678474a21cc8cd4e188fd229243d08d7f853f79e4ec4dd73599f826df9be380a60a896dc2490918792d76b7a7761452a8c839deb25b09bb87ca360e" - }, - { - "seed": "62e511a6731c2fa10dfb5f68a538ccdc1bc578c16e7efff458a82627438e78f2", - "pub": "ef51ef72f1c3e29fa159f3ad631e7bcd3c593d3386f4eba484daaaafc94c774d810d2c97e964d54da11c0b0e1525d2aa06a90b4fcd30ed22106fdc449a3405398f7f7d3c48d5b8ce2bc01ae8080d7530f7b37bddc656f530c58ef169451340b9e77f1d6524cacf35436605d4bbe69df7041209dfb7ec91250d5f81e8e18d1668c46163191f96c81a82989633577880af1e16a4f46a7ede15afc9ce8123f8881351422f69b3eb258897ceff699742871f2c2a9680cf8e9ecf81af1b5350203c7c6893d02808208092e2976adb732c9d4f48b919d61580f19ea0dd6bb86ddd200cee38d631be40936d869c50d9f2d44537b1c4a6e42407c427b41fa05b65a12386c67c0589e2741d580eefc484b46aa6c5f7a588722f6f6a61509e92be36992da24182d50a4344fdcb8214a1dce582c1763fe83605b3c05aa678868cbae21f168e10d585b83a0d815ed9c4e82af259de6c0334c6ba3613b4d909fe6425204cb344eec4370f171173bf4280d817bd3a60d8c6787a0567a28e08b931cedb65e236af33eec1f40d8f5626649a9f7d94aa3a92a735b33ba79f755b7f0d5e85242f71bcbac7bf03edc47a7170c62e007f2c0fbf62738a4c2b4d4da2a3ea1d297ea7f0c2035ed2d73689389c8e2a8016bf17838144983fa4dbdf402380e2dbb34dcefe65fc0fd8a66439794ecedfaaa71d767affe9d9b5de20b5f6ebd276b474547537861f4b09bf224cc0244effc27f77380e90d9adcc9f51554566f9c40096e4f922ee4ad9e0aa1e3db8b1f1067b68cac4b5be9ec9b055194d9223f2cdd7c1cf244cf6dafb0ba08505d009b0d9878b555681e32d47d056139d415366aa5b7dab20333aecd22e661204f6ac710fd8489e24cf4e665ed1cc4cb6b38a690eb5b44eba1f664c7f3ef4058a07b903caf36eb5d53ffecc16d217623984f3ab54696af2f68b3780260eeba27fba1c968b8af0cdd8e3d53fa9d307cfe3b7885972bb129876cb12fab77918eaa6d4de61e4038c3791b9d56fd46c7ec08f2ca37afe5e88b95a55faaa3a0a014ba87cae8ed39be46d9e3d59d25c48a08aa1120167b6d03e7b829dbe1f53b3c626abd9d971cb096424d66053df2252e01a53d6dce5670a0bdbb79cce9982ec044e8f2efddc47e90aa819fc6d53c63be6231278f15bf5bb295c775c72e77f26d4e24d8ebc88988c08ab1e4a89d62ea91a1c3c66c102736854b2a04dc4cabb39330960a34122c9620df3fa99a1326a2b6e56eee28708e6c1e51dd1b442ac0b78eab11a887348ee2abe3f1541fed4b7663fa46b6c17fbe2deb0d2f0edbefed39c07d16495feab5fea1b07ed6ff827bd0d34f2063745755cb0009660a2099d9cea2db9ae6b59db696cfb7082fc585046c03a4861f798638ce6761de09f4112c52b4df752a34507469faf20c302e33ae7e9cccac61123ac80e2b7368d68e21b14ac237ae3705a4e039ef57d6a93220c644c74ea59b565bec30777ac494ca92887b1d460f1d6b0cc153201948076c94847453f9afb845e56e6d8d5d6d4c80a1d90032246989f06fd556d4fd8268a1221e1825eff23049724a686c50f9322a2778d85cc368e80402464a578c98810a3bb7c73fd347accc742aa20c096cca8a9aa971225d78f3a5031b828ae7e537bc77b3f956648f29d4198ccec25d05f2ceb0ff38792b727bc0567fd1820c8fa0d4c15b3935597090e91b961bc2dc4898f184581cdee606a0a8f23becce52192de1cc9f2047b5d28bbd8082dcd7679c923344697b737bf564a2aa5372ba50d245e80b3caeb8b615767b7b395240d844711b025398a4c2e35837b5805bc97e4c36e8d8ed45f57fb4ca404f484446304e5a548309ff4f024cdcc27e89d38e1e4e131928db431d0150fabfb2ed4a928b167d1e296e68aa860eee76104718b00340872994b369c368410b30d427175184f5242107ce1b8de0ab862796d637abab7bf5e62a4730c8810e3cbe109a6ed835d66f9d5c192632cc1f2ca69f675debf82b3f464de1e5a22ef221a87b6d8412296aabffc87e86c1ec25bea15f0b193d5b8d5ee58fde46ee76db19f6efacecded8dbabb62dc0d7c1b7b4ccccfc5d6baef0369c16959c7ee04ae41283a187d8bb83255cc0081ec18affd608002610b168ec1fea21806835c183bb37853b3f19c5121ae3670648e162048f248bd669ec2e9f90869264b7629da97f8a48985d59b5e317b5d41df7ba781564ace32673e4ed2c267429bfc26c03dae87bf1ad04e600b8ef12881d00ab2bebb88be9b80db3a59ad91baf9567d3f02d38a84f01ac9df8a6e6733499448ce8891a7de203660f064cc3c3bd9505fa9b0d4471693a72ae18e35f52e218629bd7a92a3811eabc1b3cbc78f36f1209ce73d536e9ba3539ab3d6070f493dea35c9921bad86cf5cff9283ca21260d01b5293a85982cc7b257b007dcb366ab842bb2f827ae1adde271a3fb87b801c47f3b350e46f15aa15d76c12637286be088eadb07a66139fbbf4ed10fe023d758e55c2c8d890097125f4608eaf88b33ab5d72edd4479059a2813cd074a0e34cdd75d13084bed9e7a006371ea1e797bd57dcc737710db399ff2d7c40b05577ef13b8fa0a04496276bf54e1e6d1c3f9868db83f854d22b4ca511348c1c138bb095af9d9295fa9acf1e34fc3e153e0dc5e3fe6c26732b91bece623d0c0a75ee15f3ee55725b544b88be6d7d29fd77c18e063696ab7db9c7d9c7728fe418e0ce81be10aec7f2650e270b60557cb36a88d18f4", - "priv": "ef51ef72f1c3e29fa159f3ad631e7bcd3c593d3386f4eba484daaaafc94c774d8543967e2bb6ad85e15a3179e43ab6210b92c397ef2a36304015f31f60dc83520b3e2e2c7b7e3a652ec0b51bbd31658bfaa01beb6ce0dd16703e8306f1421cabbc2eefd701d60e5f2072a86796ac63a284748de25b6786d7576c9591bed5250d1121664437027712683823110134744782325716701825326106281417512402562610760774070343722070662367530147028781502758603157256305388552722426744506877140170222115755788830108151370532112385248757273210600417046550866454217847036112165217026334580616264266850007412410034322610722874412460415117243752444301602835170505851723667537487687808834221236561731042711113664647265734388234256740808277021024657346336844647180827423804866772028353351361670188658044347366350218124262267334435473855537211130380776088281881551766412145021645553875408724137851647668330658315135038267670382522043487733486060561457458043303027081056283277024535724768402670634777386227288035465267040734338784170132363651088253345304861706644881714370321243303456008237433072503686580630655646152582141715035716673665747140801705080317547517185862266481747431722632188065665210410582248202410334706237247575063208513068542270135344480624807537048480257675722323868828523667548614484014178247848124228773143444620546765572057224808221064011331533864761613330733788818550157340764213234637215043534188225246248281740085824730061387131717516063000018352515166156772488565363385310845267712035500857213573868153280775421661767877171368115267572412817754047622165670213137627105670022861852722630553286872248723225586151310467404677764356827417400515120767731720865132638665281483360808157072283037470672371102636515325400318878128348651077203370773663621888364417646737251134728117508742145812273038200087512187114012422063043160048858500181257281883384253120871138472364018411544174868763812527841472624285482785457751546051004821681781406613433481252758641876587085482852562232237523732553411565212412604250652414531618530613526624881737841718756787780272121431872321183822088511353210454732244658312661582133328744116472840474843221621543832313310685346707326357765544520442308307863180375243803077277353233600485441327804771085561221300415863220114516267846385655746223526784608523021285328004700858523753543662754344646814246060073571775452627175168743175130112638655838615286783432204861821730783716411812363468715234157311333307828807358242827006155513883707261038435330521613355045286071466437258168088086533315463186611606788828853586717026080606737676270286022426073737051117462454068011642116863107044530477611414484156003044801451425172355417510241275561626552532775433703464354358238878657601860456477867740546616006031482073282787538313203724131644133801723168488715667283314218312128313170507635704084481126205514816851386454877547178307011008511063001268188821288520661657308875484062782067558134202582486678183064415640006521703113811861612754566427581001647120348066328787758180026152053480046235012435117513720852020136141848740456316226257681303354467224068344155288562637885645005055251476280088665121557083876761876614184437734187175a705de4ce30dd419a30fbf87f172f493f6346dd3fa5c18c5f5506f4da575f7e76a12f54d1483fbb94d05afa2eab6115dea5ad6c86943d11b5f914174530ad081e5b99d3630652bc23534c4dcb5774afd15445075aff50d97a93c7c83d80ae7dfa051ef731e3da1960cabcab92596054e42b6d3ab9d4324f147f3737792ea623a4047091f692a02f11b46c992509087b4bcaf1a3a5b961e52fb08c28331a26a7933be9f5285a6f49f617b504f31d822f8a7716cdc23b1d3742dcb3c5e039a9dc0c049edfbb1a615de470b035a0cc7e15b6f1eb7a92f031541358234e70495c375152ecffb86f158172a0c63c490ccce17318386a5ee54319281ee85e53b6fb44db01412ae8e8172fa3a09a4907b7d8af2202801caa448330e8cb0fd28048bf01201acd838c30fbfdf7d01626574287d93078a0cd752800b761dc4ffd79e997bb1179c67624a0bf3b2441c9e266c78c07e99f788c55a4694005f8505191ea20b3a6c41d2e6af4ed78b9b48141f498425257e015805244d88ad9f7e7803eeff88eb2c74d940c7f4f93bb99cb6b582c0940d412787081003cb9be3f3d2974fb0c5211b8c7746f8c66d0f5db018bc8b5dbb4c5863c10247083b3701904fd7a498ea1011ec87a31d3f22e3637965dd63f564717c737cb9eae48b00ef49f3ee4d875712dead9634078fcf28ff19c3dcfbce7cea5744dbb1befc10cd4b01a3e818c244eb1330f7bd35c2f18af7789a2040c09f040505cb5036630a7f3eda0962b2d5dc590aff47d6f1b39c4073f5cbf139d865d531828c8fbf5c0d5a2366aed1610974ba8651d152e2db71d5fa7bcaeb56b9c0a73c1addcd35da6828fdf652f6e92a1a0307a3f274a9dd3639402774bb62af2cda387854450e34589f1de919852de1e7ff90c58743e29ea4402e64e30f75c8329a5ef95f66960904b245aad166ba02d685589930c4128a95612826bd06999a967f9147b18d3e966c3a9071f709671b9cb6847ede93ae225c70dfbb4623cdc0066dd7d13788ca2ee4acdcd857b8803c01cb90dbb650b324ab2bdea62304bede414b4422f7610f113ebf9b7e137681f209ad1774ec5d6389eb46c736d1503dfa228b7fdf5e69beda7901f61f2024d9699a28e3b3af085eff26c17b962d6b340caa2ea1fa927f273d676667a1a873b60607e7ce4ee1739d334321ffdea839b9b9df69d621bf1dbda580777084614623500e3315a570abc6722cfbb1e20b32fd410680d87a789648e00a129fab4ba628c060da271877425034a52e2dbde5720a333c3cbae2aff7638d3005553ce6c69456e835e23b98edf88d5037becad644ebc0413b77d942a73b47c87a399e18144323cdd51ed50038485d144344f56089aba4ed70b8da96a630d71eb80ca91d410764a030ac66bf04ce2a837a345747b1bc355b751a591b95974d2c7065d14c8db475abd6061a9ff3ffa4701119de5075cdff32de15150222dd9f6eeef8197e73fd6ea63c778dc9341fa9f312945dc20e8e24c607512c501921b7740179f2ed8de976ae0d6f8ee5d821a3668cc9ada6abfae60816bab6e67dd74ab8d3c271f0be15c583a561aca92a7cb63f2bf60c0dee6dc87ecb3c0c1bd5f16956c8a937646595822dab1ce09b1e194c77735a50f8af265c630d20d8612a3080b2fb41ead3977d177aef12c2498df63edbc91a1bc2929283f7c66aca5cc4b03d9a410043b8003419e1cc5d09293d526d79304ed589ad6ec522d10cef80fe742cabc90a82a209ec4b0bdc1e202928be4a6defd6eb37cabf3574dcdf357cab6af07b22416e82722c5023e96cb6b518754abd8dfef198474a37afad1900755bb1de56249d3c5be147954670c91c4bd940feeaf275d87c04d2934bc71214a96bc3502448156f5b4f3ded83ed55149def3cf1b39f43becfa1ecece545111a996c8b6f46066f759c8f307c7acaa31a1823f27cfb8a0fbc4e5a11d6ab0a180e78ae4fa0de073200df8717d08021b72f1ed67089000f5694e518fe3c286610e0c18ca312883f5bd806cb6ea30f4baf513fe183fe3109c43bd5bcb42efa5fa0a5d6ff7ede6cff61da65bcc6ec78ba9a35fc2b05bc4d3255a19c79332f80ab35177352a6dba730c6071099f3dd56d510a129e6de2d38ad6895c5b917e22cc6763cea81e8b2a88172aaadae3600a911d34a0aab6dda0374dc776ff50caf62801e2daeffd58453b27e2a367f24106e35d1625936d31e3c26aefb9354d70417cf264bd5b394d5ddcde1f90c20cbeaf24323bde3078395cfa5d9aa74f1e97bd4628b190f480d717823786c3ea5b6c0f54adbb0b2dac9ce7b1cdc6ee67b036f16cafa4d25f6c74592e535302f8f3ffe3b91476bf588cab45580cd0eb2c421183805df21d51baa4d6607e40469a5509aacc29605f64c1e48d4ff1e91674e52ce9a6d5043380580ee746cecffa49b6ded160b70b3c62c43a233d6f584e554ea5d791efdff310a7f5225e7873b26bc5283495cb1c3c2bf64d868b85d463ecfdd28b6682f2df7e57840f535d95153f6afc2bd713228d1e9fe546b9c65d665cb01603c9fa03bcc4f8292c81f7195fb9453ba15980bf464ce57999547175981ada808847786ed93460a43627bfe051f15f871b38d02c9ca224af4f90e0eeccd4b2de7e7afc950c2f770ac94eced9c18b05da5b7067d6a984624f800982f89e6e0385db626203f958392b16e9a86febcbe65231e8f3ef03ac7deecd07543c8f8bfe409c3cd0eb88cc39223366cbaeb968eadaceef97c5c7fd24c3ba4d97c898734c767029bdafb3b11419cea7e2e4f913b85333990b5b0f794e86342797d8abf0f4742895a0d93d03e43dc03722fe38858e00976981c555db0b708b3089d344851ca1cc42c7f9db437e6f2750f21fb4243557f70a591354621e43712a047ce2f8951483719ce639a50c951e1e7326a7f089d47e0ee2ba28bea4204d8478237ce7de9482ffc1a8b7d3a56d4022d159c5099a69dba88c71de62275be5b1707b4567930c6c3ab019585998f5a1f167737265df9f1677b9ac771ad5a1e3f460394fdc249918c1911668d7464786293ae2d81d41c27eb0242984f922ad5596be51c31beba3b9c474eca02a440a2b4e9f4767719a92632285d176faca6d06dab7ef77b8fa4ba88168a9802912b3b2b3326fd1ce0a1c960cb5a197143f547b657038140c79b7ccf828d81a9c1d4fbc7f03fbdd2f6edbb163fe0db9bb9b68ed9389372f0d767fa985c573461a5f246ad3ba30bb6c90bc205c763677ca8871ba4682939f64180afa9cacadf68ec838b56e6a71a952c8769299c4cf572b205bae167df5fc183553c152085b54fd5173bbbeeb615be96e737c5c1a52fe068c71c433b512c5ffff769dc2132f94fd7e1f1ed296a061c63f8bdd401b76e602247a109179ebe7f47e7755a21baaa0f3e5118a3440cfe071b1a3d998423bef4bbc48e2c172f1bff8a5fe505016c9270ba787604d29db56ec0b953da5ac54faf7505fa30516a3f060e3894deb7c5ed8175493db7e246d87467c2021c" - }, - { - "seed": "bc4ef6c46cb18061966cd872d2cb9826b0220173e42f11b451dff93c0577cdf5", - "pub": "172044f0965950fba5280238696e84e25ac1a1911fce85c13fedcba82879572ca7cf41d9bc636574f8629ced228ae8f626fef7328ff39df8079ab8c24840b1241920b4849e57981ddb978ab5b4437ef87198e91e20aac7278ef115feadc43e58f9c0f135e7833d289a4f33738fee0dcea8b50db3f0521c1c3c76987a7c82c0af3c38c59ae1a888b9397258cc71340ad2886d98207aca566a30605c4e2e545161a9bce5488870fe6c48c13b0f47e5661a7409a6c5a568988c9814fd2862fc5b1a690841478f579ba587598558c2c07e988614b7d8628ff00798f57cc1440a0c5163156d490f3a3390d4498881bb67a58964b73826446965aa930537b55a701f4f635a67fe975838b59962dce9e020c77352929fd327d0106cc0160b3ac5f63252f85c151c889d096c942939ed146a04a44c9f2395cab0f4399e1f603fd0e3e5d4e7fc1db51343425d8cad80076fab19e3dd33a007903d12caac1673fcc06c401e8315d9603cec9d3c7f0fbdb3d00cc2b23e10df63a9e4b2d3e0ccfeddc5da1c2207a7ea9a0b81d4878a7caba63e494a67466a401d1988270f6de08608c304ef6316b74b39ba6ef4d5bf3b66e297b275b81da2df24fa1129d88785d558c3f79c235c8243f0fea80018dc6ab8f375eb17a778e349a87c7b5de5666d17e41154bad3c5b00e5b07cbf9f46ccf1759fca574be7257f1160f65e9695eff1ff32f92c386489ac19b3322f30214ae8b008e342e21ed559a035299cb6733cc34b2c2732bc3a3a5b5c5e4370cd940fab60d9110071dffc23831d984a446fab028907a71a423e5d22a073f069a2539195f1cfddab21e3b163d2a1a3b16c749c181e3e68ea90e1c2e98d64661e0830be2e2c967c0edf86fe3e0021c6b217367c8d0f3cd28b8bdadb49329de289eb3746ba459ad8b783155ff8c151ed791dbb33bc6ebe60e6985d98ab003f613674890e1fb72cf2fbb11ee24c2c3ce6148a152a4b0f44dd890ae262d53b0a5fb18c748be880b432cbec5616fc0ab592b9732b69e6a7c4ec149ae75cd286d133e812d94c262e273d7d6053007de2609a40109ef7759045c601774df800222897974438d6ce98884fa79c99b205f00c743452710bff448ae9cf00401c99bb75da90e7d99877282d1cd6c9165f372abacffb6474e94e7c9dfadc925b7d7f14f2ae043a0b8a75124c2152dc45310fe37036874f466e088fd22384c798a486e1878e784da4c4bd790c972cf118a64f176fe8a8f6e565ee26a293a4593fc80b685ab615ca5bba86bc046c413d9937d544e9af7f23c717796416c56401a0e68043f0ada7f4c6c9e2c257f36580b2a63f9a6d8961ea4db955739daa153152b8d6c2dbacc52b24be9692dec785509a23c01e1969c1a6e2225cd3b28f93439174c104a24a6258c813e74c46fd95947d8af64d93461b6aa50136c799c140097c7d8b24eaeb87ba50e73fcc8dfe9447c228dc6438574e21a23bd082146a0e617a439bf81a9118ff3094b8d794c72ec7acee9e60c24e151bfca9d51ce368904aee0c608df45fca8c2c536a4f0f1038f280d06a15ca43fa836dd54f2a2235c1ab14621f8f57f10ed45814249653f1de0fdadbdab1e95fb502dbe85d05047e7caa8c4c6892b421f2678c8868f852a51f0e5bdf82f776dd1fd40dcc4404db2cf4625597fd5fb69f10806866334853f0b40fcdcf64a02641226bb7bf4f33cf8449ca1921380091f5255da7968333ebabc8f9a84f6f8c84041ad2fa7eb9c80f95d874a860ed43980d7597e4789f8a69424da042351ea9d5b19e5c128f8c5dc505afae0956d913193d1453ea24fb0d8ab64584718a61b447efce208312c475d2074928db96fee1bb910d06dd6cc3f474f4335eee418becca71138a3b435787b4cdf209325865676ee3dae6aade50ab8a075c4ec28dafd308f53028a5944272a9d2a6f199f08fab81689786f08312ee0af4af1fcb0ae0b693627c1254af89ba8c1f2613b1d5d46c0fa308af2372248797cf2b3af9ccdfee69dc21b09bb390d4b2afa00ee51b83065ed83e4bf1e60c9cd0b79e5c7eee4390b28144fd2ffbf03fdc97a4aa39361b9ec50a2ae3bf8c931947de3675849361608e171bac9772296bb218de9505544b50d8badbe77959219a611325a3f6093549362f07c40feaef71b25a9a7f928a001b1180bad6b4c57bec8822888ef44be1eeec17600ffb00305c877379815bfb09cfd4744b4caf48db5e4859a476c198b4118b48afe8176948e837bb8e54289f995c4900b0e8cec41a6550876bfd950e5e3f346791c4ad110f6d6c728e5e58ee33e47e57848c7db6cac53de450cbb9e1a679d2c74e0fc8a01e0d2d9aae47855bd6c1864af95ec834d229809ed6d3096113c199c156a80d10eefc8fa3b41bbd23e5be9e618a379160ffd6578d158b9e04790248737a43fc8999d25d549f67e194d992e63e51de388654c3b5956626443beacd55f433aa07b010fafe318b5763bcba9fdcc17c88945fa5358fb0db345ede62fcac8d70e59e3e326c41944f26e6e9414ae356f7011af46c21cf051982f56e1269ba3286ba4ab4142253e75fe6f38ef6e43a708d7f12e18ccbfb88b31b2dc2e3604ae8067a29ecc47ba2a7eaec61c20a286ff7c2ecfbafb722120992ffd8de17ddcf8120a77f5ab9bf66e0add0ad97444ec43322950fa02d746d4182d649a6407d5adee07d215566860364df3f554f784f30390b1b4d942148525f7f5b253bbebf71efc2da6944bdde76bfff42b", - "priv": "172044f0965950fba5280238696e84e25ac1a1911fce85c13fedcba82879572c29c756d826f40ebe63389844b3856fd107649ddc3ab99121f9b5f658a25b2be42d2b0d0af78fe1a314c90b3a426395967dd3bae3d5d1029dbde410038e39bbfaa7e20fe03217656bfa7930d08f4bc65e22ea8fd2054d1ccaeb3071650956921c8818383516546652345845348341062226750117678070784570688375188710570177501547154781433305500441388730375103588405375867617654308866302441600407576855334525682615663181476154841163774257413648636855878347220644304842024115888285246226138068538618624402515488050667520351648113356388605656772231715728008745145588726836117405018742345584424117700018427422172663251250586644286578757304668042003246205338202634818086486123301785675071012243767856118835760130687363568514152268258478147501550424740841243831124168575576778672513600028474115545671848450525620062025268211708511303805861272607274170036384165863223506451565485030532523838221603121287121258746072176713758303632550312407040655188220360357083342722457032075015106782627515768051832500124057822141806717818130204348522116668168451131021286034235335052683755014564880081527078434626244324244510065258144513486042326238540065740028287018174303318278605860268612373017402063473525711430312023244056812545442844100520001864131458455054357850851616055356500742453276075824111777566866705768584830046800321427826811111278128707133771780512815062885416415722083566437861458372806671084678275584322766418754517617566503460016327270648231052836222025133383052468854188306714172464176800512243177780687715053575280724703280270467263745336412286256741502851718788040761600037416853226678306578787264856847665327562026070278647542104163834357747751682268186422832211685401007454675858764182640437071260473443336570828403305146626232784033300107168103446217346137550463081382500454211446123826604371182686275337146882401545335814524011776880487111118424037210424342370242086353287448665040282354413775244701060055434041608100180153521065422144718432411453616532145776130503005125174035851250505745133537151673466754538347058334505557141046336117404485764114821312541582861414507838063640842508474877435530016238621821578103225262201873646007042385113361266433360344375647126042186828638601077581056113382282548525480625002560854472737373661454043588228486646342684336122607353740480842165545624654407006382410124026814128213476402880362710601084361726087002868561358056824863415583231157101337220888846877801156782588770147556680432713113728653328533633450458645337136485473234337704500632556522004715764426011055020800404283451041078541112463436778348678102033630286016710360132806074553635343634681186558240305064843460704424377205042621258166181681515748037366075414103086201016510622332567241352646460736353614088313652185275227160484630482480168165272140537778813161341883025552377040525524854466625216273363852012381002677764353275847134654001617637546856066738302850036854362132481856731425248733072822146707717830226726020857302425511116774864817318644468555074138657504402057020263158005116668616551570538040051435731622821807634486281403783750583701308338531138562104f2255924ec380d004ea05a4303e25e0c1778839405dcf83b74fd2754cf15fdaa6dfa98b2637dca46e9dadfa726ea4ac153ec7dc0ca42e86f26d03494e5206bd4408df6e7c499b5919869c447963748e4446f2f0c38ac7df52bcd04070490846041583216b2d157de1051b4e55ff75dc6a03bc20895978e3d6fa56f43cc5c7cb645d97c028894a25fd2ba8592bbe355e903162615150cd05416835570f12f5a5c9229aa1a9d7da3e4d2da4b3f80979b944a30004ead2a590228a828c878f5176ac162892f11369811c7a5877771a00c47edf2473a4c01b760fc2598f505b942c92ce8483ca8a3050d63522b7d669b3be2c3cb85a3bc7e618935e6b72290e2570f719eff0fcda400db8a7bbcb6bd66be529b200ffdaca580c0cde827ae11f2d920d2ab1a55900067a4e3c0464c80f12a7ba1a0f7e8c796bb391995a439eda1f11aca434a24bed01dc28ccf448791190efb864a094d564b3d23005a492d0d2f1d6845472984c8c0822822c9e978f85f9e36e38bce8ff48e3b485c7d6888bfad21a453df01be666a4ba5af49a1922bb368ede947e12d4ae08237912699731f33aaf445c8482dfe2ab567f7b3b256956a800cea10765ba7f10d5168ae9053c2a341dbb59290437de92c05a93036857a19207821ad6693db7552f22229ca392566e4a019bcc21f76ad18efa19150681b4eee85d1292aaba0a6792d1514d4a550faaade32da084dbc9ad9384b11d482b10f8fa1858a9e558383d5ecffd75238def0c09c9cbea14871a310fb813e6792897b5054fa56371da801edf8ab1eb122bf4a2f01a1511490a48b8339ba9c6de477750f5feb46abc9e3dadc5c667847030d4a8cb532b89adabe7f2809ac03c4c88b09313901b6f358b3f9ee0e48428469884974a726ea63b675e51af76d4ed98f2108ccde6c639473bb9979ab51df674d1a65f889b41d9b18dabfb776bccf4791dbc901a24fd9ebc2fb2c9452589cbb629e681393c019e35f5d6bdcbbcacac054ba8656db830f1881ffbca556b0c6ac73ca5416abd5aa4816f5bd277df79d984a06cbe50e4e0af9b9b150099afddbbc907580b09745fd335e006ca7f61934b890beaf2b94f52f99befe94811b2827006042254cd2d8075a0b34fda4b31e7420df4d96db803c0a62fd802952cfd8e1bd3048540d1918e52666e185a21564bfc9cb42afba374979b139555a8909dc7bf49c4b4be6842c3d692c67188c169e10ac30d5c988165c33dfd7dc21269d276f1d3fa22c10c9012a5c8a0c8423c4838a62302094cf3a213c5721087aa6c43e589c3b0fff04fdf91caefd1498fdcec993acb4659935d5d90bb5a709704774181fe001ee1e05a9dba1251115a79173b1c33895ea761f0c5b6dd42bb06e96765d8c242d457a986118faf8ce1f089ef1cf293518e066410eb04ad8eaffbd0a59209e2053b7ff0c2e221a6f27cf8f05022bd91b0aae3c01ed28b41732a4d89cd55f7d491f4e431c40a83752d470aebb54ef96a630576e8da05eaf5218f8c09a8d1f3c80a90dc77f15b3b44ccced6149eceb7569eb5add3873d2a23133bd723f71a2aa7b0d3e2ee1cc75493dc0361477afd5e6658e9787cf117243ce7c17dd8b4fcaf65b3107ae60ca15a8c5fe7a9745e27eb4674a6b55539b445843a2870ab67bf2ac6f80fdc5b53929447c6c0a4b42de8bc3cd22783a17b5ab083b4649452913de9e9b5321e86544bd771adad0bbb5417213e3fa62d80e92548a4aa7518e2462b08eb141b98ff44d6b4d7ccb1cea4552b75ac71c1f4d10cefb20a6c703559f26899dc2693fb287574455ef767bdad3d668ea8477b4e5ff4e263c3c7f50151487480d7a6c271412abb763748e342caae563a2b2b421e067b275f709cc452d011b2af96985275c1cb1945172cd2019388894d7c450d5a1db83a80771456d9d0cf16fe983086090ddfcecd8be9f6ae66ca936fbbc0feef1f73dd2c19f4ed1f1f2855906a2ee18a100b79f1c3fac6fbf990982b0139664c08bfca09277370f2639c5260862ac4c7d03b7f4e48eab9df4e9050f67a50fc665b1022b00b0e7635d9462edf1d602e04808de10a0c123dc21c4f8ba28a94dc1b1ef5f070f70ad18b6becc8f9a529903502aa982e974a6d17fa57a52ba878508713e7bbdf882c2fa50fcd0ea27f54e1a5fac2d4101ab0d6f3fc3251d922ab2e3f90f8d61598eb15c77869b32f96d364b70b609d9630e8ee18d71a4a05a0767dd2632ace2342f037bcc0d85abca48f10e3839a8d727ba55a7adaac526f63a60775743e06d61af9b9c20a3f10de2b8bcd545c3296274751aeab66b7a0883cab9b07d48a24cc567ad135bdfca30b61c47ae969509f34126eac2ffa5f2dd08984a23430b7abe4fb7dcd8a6edff1bec22e7801acaa855fa5f3dee21eb1fcbf9204dd2586f6f78f775b26856ecae89c80ec645372c7b21036591cc20ccc96f92e16e1c36d4a0d80f8adf3d8ba6d2536fa67a5f9fcffcf291c29200f9592d3ea56f85adb431d481f4297085ffdb8f669e523eb96bef366de05d2dc8fc0485977ffbd719dc5cbf4bfcb3cd191af4bae90696dbf52bb25d164de472a64c57002d434a1c29bd379d72a4cd86c1380bb8132bae06620dc219c8e35d0b042cae54b32358f68554e34d55275cbe89e9526d5285818d5d9907b52aa21f34ada8c74576c46cf25794cdfe19ab419ac44f3b05d0a40068945f7564b17012499d0602b4a1774002d18e4f7dfcaf3e6cb035776704457632913826b64c71018c4949e7b97c4a31e042cad3d25ac3b47e540d3d0dc6491bc021fc56328e6300462d8820ef3d9bf7a40fe779218a0cee30390a183f571cc592fef2abdbd47b3a72f1e779815c0787fad9a4d5f817c20e1cfc2799783f09dcbabc4a4692538f5b8a8f71172a738f947b899fd431b6c82673f78fb88d528649e8fc794a1d3a89e7c3db3075c2c3ad5ca00539beb10c4fd6169a05836a3fd524405bace465d0aaae4ce9df3836701cd7914382c27e73caa08f1b252a4b7eaec1c861cfb443b28acc5ffd0058e0e9ba4864979c7ee56a42e0070cd18b74340d92a83db40276b1ab57f84b6abfcdcafe227c08415700b6163b7d57ef45ffd23bc0dce56f1ca8fb58e52ba415a58b87a46078f44ec0eec9482e4e032d61512ba21acefa846b408856d64a1d868ea98cf4c518ef6d0f9cadf76f13ff1a90ef4b42b49acc0fb61eba9d88a51d6f9143c3713c91d623d173ec0be6dcd11b02b2b7ef08adcc1c7a78e262441d6d919e3e3aab0b61c7acd6c5ef95908fb789d44eb01e505f9709ca1d47c9afbcd88806038da554b6cd3cdbf274a8e0292d9b451abe590d7f7b8b32ebc60848aa5c0528a8dd435498ee46aa7e89f72aee8d96a590b5fa434fa4159e190c4a668912c80803cadba8970d57ebb2fa73828f955754f81f2a3b5144f891f886e74d3f2604b0e6a2537f491b786a50edbc03cc756c89d59c7a29e372aab728fcd082a872cff573d0e8d0c6c60bca9b21627651bfef05975499bbc05b2" - }, - { - "seed": "135df872744277e90019bd1e904dcbed63741d863e82388b61a2b069e509b25a", - "pub": "60f19c2888d3332957f177b055ed15294b33e36071d56cafb5318fed1c8c590596037b30546386f06e9fdab6ae2e88bd93633e9c27ee046cf437994d9fcea1bcbed601082da3973209a408440cdec12af383aa23db274e7393884cb7aa4672afce26a95511ba62cf43ebfc7945800d79cfebe0c41fcfb7a7f1b11dbd5d530ba969a56399e76ef1e8244dd225204aa140c71c90400d0e6a99593b346bbe05eaf414ae396f169911754e3a631d9c28644319bd4ba952b7e935aebbf0ac81326a8fd03eed551623becfa9637898091fcf12ffda8cc2636c1699909804fbc6050617f4e0454a45dbedf647fcfc47f678730de0fc9b7793b88125dd22da136105a23fcd1e7b581cc9c8d62204472bc2a8f8690543812a157ab1d3f7c3a8380bf7724ed623b938318cc45d1d8b907c460e1516192be22678a7b508477ec3ffe1c2f085146cb921012010f82af16ed8e8a4185d4c77a21c1a6dd6b56e0721ca1f701b92b04c9429c460e04c02e07345d6305205e21dad975783669e4ec89521fab64bdb3a31eb76b18c33f81cf39d5aa9bf1b19f819efcd38aa04ea3de374a6e155f8457768dcc6b7e14d2700ac4248710d527a60cda5a2dc3cbd0e74eb82625a1642cb80b7310a230392148a4812ca7a64ec7dc9acab74c592a1cebd7e4de2b05953b3500ae2586b4357a511340821eab6c8f2dfe6576487c93c47b4b2b76ee0c96552eb31a5c4415ec909f74c5ba9513a10ea8b54ed292d8d76aa92cc131be5f3fb10de22d5480d88499edf7c3b265b96dd9cd13a8964c6d642a10371d69f6f1948c203af1e321ce53c48ae77a06e2de4b4cc942e9563e94b75bf4284e7eba1bb3850cfc2f1e9ac42d7afd4bf6d7f99e621ef640ad2beba85db0721cf550ab3e2bb3346b36c9d13e34d7c9ff5fac1ec257dc2b38122855c5a762cdb08fc3de4d546f2fad9b51a3f6d5d11aec965bf60b834175dc3de02431b2a82c528689ba90c735ddad72bd930939ea04e750e33bd3f94f47d4f39a60e0ec2b30be74cf49ca04b100f470b8ac60bc47522064f540f9a5d0f57d19452c02f0bd526d17e86942dbfef921d82f343835288974d4daff657d0d53a08d1530ed85a50f8683a98d98b402c67fe58879687a39f05192a082c830365d577ef0545d4d1bc183a2ef070d817ca4cb941562b4487b4bdccabe417567c6c5dfbd09f512e34cf996a3c73a5d2e1adf8ee94b255ed8eab9ffc7cc5b1cd8d213474bb1213e47f6f7b040c77517c58cbb8e77f5165c590691971eb4587fa441410bbda483ae2e92000d2c96869ea239131039b672d125034926d0b31cc481ef36cdecec45e3258791c520a185249adc4e1c946a9214fa6d29f264a07fc039737dc0a4b0faecb74a8b539ad875c9bb2d6eed2dee6b69ce2e12e1e92f3f0eada8a64af5933bef893c0d9ab0e4a19b18a9eb56f7079d7d730c1695beae4821cbb97e3d5752bbebf6666194695be5e1fad0abfcc280fdfa1fe2bb45f371f642c93eba3a0d7fa69fcd30af866b1360a8ff6707c54504eaf05af44d2f41670033460009a8c7156b24eafdb2bef3a2fba97ab039518eb8950bb8e9d07d5138af47f43058efd57ac450e7caf54c275121bdac4c2aa70cf6422f7910b01d058cb4806d28c55c69fa3fe7801dbb2c62bfb86d7a0925136c4055ffdea8f47fe22332f09a580ce44da4311cf51ea68495d69079a5c9c8fb442e7681a021a32eb88ae12ebd16f91753c54a56435e5f244f0c2ca4103dff9aee7e780fb423bf148c9026ec9e649aa80cfc411310c3440b5ab6fa3605867751790ea9a54e053c81970b3cc5cff5fc000261616524768f7e06034b55053ef0b7b24c52aba0f4a40c56e7bb72857c893aa25bf97761819a2ec8b9319c8b8f55a8042879795d06971edb9a63d85d2e5839cb704d66497508a8628ad4a7b8c862f965dacc4d9be011eeb5c46cdb6a2ac03c6ab7c72da20889e6ee48b9d6e84e2ecdbcaba5bbb7cef9ddb7b97286185283809e6d6aee4189ac17ba586a274e5da9fdf56c0c86abbee67525d27b15e08cb949f8f38fca263271b5bcf92121269ef692ad7dd182b917e50dedab1b8c5a42621dbfc682b2767a4c91e1de942a660d3d1f4e998faf32f652c68c09d4c6d278fa8de215f6edf6e254ac8e9a8a09dc43e93adbbf8d9a6d5bdff52a0f9a57cbf07b2f1c2690b2d4d1b92012a0062cb0d39c5f51e1357a3a9f2b3f063a194bd68d09412dfbebb39a19e0b6994392f9925d1c7554456d0d633549616d56536b4f6ae1f0c6f2991899da65bc1b8f2913f05b88acbbae77f7be27302eb04789e605724884525219327477e4bfbc964207408df867a12c8554216dc7f0ede2a74f3450f09719965593ab620804f6160d493437bf2647b17ad8e9087fb9ecac796362b20c47aa45f5f0ee2a3320d844e78ae6df61597e05b25b4eb804161678c180c70978b5db16f0532c524fe4644507a178a31d84bc823241390f2906e2a5007d9364ccd5e332e65595488f65ce00c15c33b5a7e0d2aeb23bf53c953858130287b021af19fd83acec0160129166b7cd39305b32029423c9eb7c1c86fbaeb08302e8e98783ddc23dc2c88a916f061a17a436208d565b2f29d31f38881ca031ee00ffdba53d5f27b1cfbf8959138d3935aa2340cf37f8f1519849a087da12c3d0e025e33edc19022911c7f78f49b1d3fee3f87250e38eab61b2e607173f880b9534b370adeb83bf9aff3cafd9bea06878e66dabf", - "priv": "60f19c2888d3332957f177b055ed15294b33e36071d56cafb5318fed1c8c59059776bf0982f58c5bf8760131d784cbc59c83506e9c37073a735b862a90a1351ffdf2cbf21f6c592f36c142e7372741317808ced0e64e75242a8ca167dda0931c12067ee31ec05cb5d76762accb588d97f885da913edb932fd9efc597e31c8fe7483732182417476267842312383478154743246465608704018564385702145640032387477480015217732076670716666467833626011865105780352472546415744556138516780087816437287418113876478510168466361118214334241670114075453510780284573135100347550388577701188017176163033247283666855118737431883475501656605683610738528276807102471644770484440320781171351481611644187385155343613247758636820584746160088566426010428203244046441730233448316034754248183573334761217257455360176028465830788381643240768766280464653231063260878410470574307373316874208716171123303817623837725475353711451040420210541882572050248682047242423200011856287765407446474167417575752066354152702022122578670844232737845641088335275415401011387716361864551521567112453813325131754308472287050122011151372646414852012325538044287833806555000572835360174353656765502258874142856141381211338024426087777686324317468856134168305145721077050524706654710068461234873625832256211720256300534682510444126505380610114274108128652105757116102101610027146353055681174423780414631814766604742016505380053811753008368165204378032838721314303164347700288275788623102537480584471452714476335173848668614437618187610552480265653710132536135642551212270583780386871528154403781704407403277421066170314475687213210526636380221070102627478732365161434256612014823302523866118448752603774022243324574346365536516014470447434451828251230234262820774158573160724435457606050617288264125822135802242853578238058441418124730762135158784477176721846631804675433384776456172658806162800784657603315350128042358401711706737852082571514521858816256047683653501611414232632543716484572216533733465564646410787800711631308540481036537622137273362580821460630373846686536351643184220531260100470718632847612280013042337373536221652732260400271713866033384882613587553853154040621820351770001324430483350066467206672766355051513856777165413015284625031416666867715458402036710374272215323506650536575663454041153038824213555822740826103470534308818637830853622438247348816776304148463123075133283488484062036787547713120366474014578455581134567708113412242521388135757240176263555784173124460318616660500408413380503574433416272072522707577581862022240481421307758281540872888122804243684675014071523047532418622155330485380820231333301134246558278003026512810705606767804263084124781578616637246768362221215416245532858754872782888871325412358451314080488111481442478110611135071715543656513067667176448838086323467381317537420507301435855664835265066015501051842518277816662454485756187478822648427083443138015222802362876282417008521324004255156877406860744830428285413554573067703281106187011234434728360065728454415716563261413046158800686358771553030874538582228413307033286145140814246244015884017253404030718260532684216764132301055016015132773621625305843836355723257172476645626154671d230bfb6ede64d1f4ce65cdfcba4f8b6167127daa9cd1a3251479bf6bfd0cbea010d6d3eecd927dd933c6784be30834ad1db0ad5b2e416d86836615051f434db116d8388ea6dd7f7bcbf7d28a72489ca067dbd3f478010f9e1ce759d5b1af7a5faf197533023b7c05e835256d849c1cebebf17844f39e36d0ecac807874050c8456855f01ec40aeab3884d384e2a12f0eda8aa841e8e0b1c5bf11e2bb6a29e8444bd802c1f460405aa21e7717ef90739e3f7661bc8f0ef1c66208e66da244292995889158f64819551f4174038ef3c2d60b98eeb43c53ba96056542a215055432fafbe0e7a812f0f685e24e66add8cf09daeb92445dc2fbb144176866ddfd663238e81f668ad55b4411aacdc07811ba48163c49056f7b442be8533d9e3a2b83a057f6a996b6267cbb9433fc85a4ddda41806dd8e067765c29721e6d5a1bb34a80333c199e00c2e3563f9f77185cd100b4a2ff5f1f97ade70f1928cf198e1298e35161cdcca9b9a832f4413b732fcd271faafbacbbc9664c43fb4c24206365e7fe7c5e30d12ffff90a3064bccd44bc8c59735cb95ce2a91d88c0a635e419fd0bac0270800109644eea88c36fd78393b42384ca9b58ef61b3ba9ea7ebe3fcee044054fc1bd24fa70c71243da12b338ac7461c39661ca4f2c7e9529ae53937800bea814bbb2324ad2c05785920af96834b994ffa29f8674f30e2dc5e502e74296e8b5b731b53db9afc4497c2a7856d23e28ae1e78d957bc73e8efa29ab3664a3fc27f5d9bad4317ee47ef6cd1b6077236600c2767f7be560ab260d07c6fe184f7b9d928242d269c655d7b896b859cf410c2c61bd5e6e5c34531efc22abd9b02e21887bf37aec7b4b7b1c7ac9bafd050ce93e6586916ba766f4ae1ea035b0ceee4bc362cf87aaf83577427c8f76bf36d631b72aca5575f48d293f451f66f11fce6f725c6d2dad3c7045c2cd74875e122f14b3d988e207fafc198cec59fbbce70c6ab11e686b5775cf08673ddbbd296ac617326d3bd9b1daee12896671cb0546a7f6a74ed11456eff0a74391136a5866f61a5d3fc6498caa1abadeb900a0c9c36931a4a25987f25e31e2a72388d84ca70102409168c348aeb13833bad91281cff1d4c76a4d2f0747448e8f5525763543e2731c97d506f826232c55c1b85c661f5fc726ef9c2e8667d9fce4d3386081657629cc1658d3ba4559cc0f0290215bcba010cfa280b87d23bc79fa094b3cb4a08157a69e3bb41b009dd5354d2ef5c0c617a72853533a24322ac5c85be8c31c3c8be7a71065978006d5867a3968db01af0165b12a557d3b0bf8b44321f948f367a5e3a5bfc9f190f26fb35527de4c06ec155607e377789e2203ff48a04f837bbae45e2e4a4f049e181e2249f59f38b151c3f66765130dcead1436bdaab9a4b813e6b2d418ccedc699f126321e429ce9837b9d00fd9413ae3efd9649ad2f58d0be9a1682d9105769c111886b68eb0dbb6b16ab16c9578d3952d24c03c8e6e43347121fc1510952228fe16cf87efc1b0e6cd47a01752df9ac81479c7434eaadb137433256ecd2d9dff8c49a68e758ac3594a0c06b84a19393935c4f6a894b0e90d7166f2f65734568cb3f837a406a8caebf9922e5327d5fa2d2bb98d63eb7359e75fb836f5d392b25d32997dadf301f8154f320dcf941d309c78d09722e17af06055ec65f2f9dd341be705134c83ba04dd32064caa6ed894ede02b81cb33fd86056b40f303cc4b236eed3be34d4555c8f51e8bc20866ec97bbd57fb754956a1e52f371e4287886af8152347589bce15267bc603e9e707a83d14b0aeba6e94205bfd62f743cc4d6c401fe1e1ca130872083a039f7d3b52cac89a56eecf96bb3244c4caeab615e2a45814ed80a153ebe5be67de0f87ec8d48a404120d2dfe26395ab2fad1a1194c89a0aafe42ea15b64ac806af8bae70e770e73491e55122303d0f0a258086033e6716e58f18519c13b13e07b4567b8057c06f68c6650bd7225de1f8afc79c0159ce5161652a10bed61895ac2495777cb165912c0e24331a21b6f4604e8d6f689e06a1ee856968e419fd01e8e36bd3a071f21f9b4b778859c0c524dea1e1f8eff0d92de8ec7bf8fc5da396046ce9966c198b0b1968ef2776c43278a0416dc2904167ce9dabde13d82676a8aa9579564356774ae62f4a7d86b43aee8ec84b3fd55445f1c84dffbe038c0d5899ac1bfa5cc258afa4fec802737f6caa0bcda4143729f233e4afca6b243cd21b44906a5ef8f2a45698e91c23b0f3bd7bb03548bbdefe24900b400f5df27822c2434471f460df2118108ac3ad2d7cf5d5d824014546d29d4fc258088b2ee8601729be1f2c8509446fa37fea4ba7d057216a14758c88e75d7d72b625c50b18baed848bc23b28b775007963c010b1710243a455cf3f4f2d90363d4e50339b990c449ed1a26e95f997ceeeaef283fc98d59c172f0cc9127b564aa488e3b18330eb1f945ee48475ff1968e0c2daef0f582eb5d0184a983159a894687674accca811c570b5452492e8c79c21f8373e379c5b189948ada6099a3465003f8a1a3f8d89565a09189e8a9f86186eb786c4491c728542acb5b333b0fe345ffbcd9e0069619b04502a06ecba06d6c3d9be70025346a4e879c55bf000b9fb374716dd20f41b91be43059ac0ee454d11be599fde39386eb72b6e195365d061dcb06aff60543117f7742ec0b0402f398ff1e3aa7777400108c2230f266f27d3bc29c547fcd0c57ec098cecbbd10e12cbc26bf290909a62e6d359a823edfb728e714ed8ea40ed58febfe6ce2316d8f294ce3c9ea68f08091659a99b3c12f4249d931abd465f8ba18205f57c46bebb5f245d1f9f29c64f3791292a8f9df9c6473418ae055351962795185dd60555bc277c8a7155172408f0b99b78d43896cf17755ff5200a7daf16112a93bdaed173a2bd934021c22f25ac6b761fec2b992bd8e28f1246670472ac2a2a76b2e15f336f211e99912520728fa86c130951a26d456c47d5c51b8322208a0944704a815975de32074ddeadf567b9346df1fb066f687354828d5bd41a0e3fd2c38ebba74010be647eb75e866cac2c8289b3a097832ef0b2fed44f6af239a7556027c41e7cd42b18ddf709e75e94360c0b404060ce057fbcf1b6100e2d9516a91b7f7546305a447c2647f76f588abd7ef3cd823cb6042b59160b8bb1f14be18af1134c8959a84e25c1b5c22d1baa419d547107791e1cfefdd112c9488a9a57dda15fbf312db3a122f70bcc5beaeefc35732070465309d2888b65848dc47464ad50acbf88da25384240bf2e3d4ff2ee4b59e85fc47f7127814ea1c014b127b1f09bf09ffafe7e748ea504b6efd20180329582abe04ebe4e20c7c508c32b2dca0be8e01e80f21693ebf250e1fe7237bf04c58e5ec60116be1e6be90655d5eecda10d59858a678a7b137f82618a913096d3c479145d361faf0e926f2d9c87cadf302a950daa88b4f9cdfa66b1d111c3c9b80259187e78b2c0dc3ed3d6daadaedbd1865" - }, - { - "seed": "aef72ba72607b5d3e49c579752be9cb9fa67a01b2e8b654ee92177bba596066e", - "pub": "a5bdf0f8455f85cc9f37da908e52a9f70dac2c1473306439e4f3051e897673f5cf4217cb02fc3bbe5e08e9a257d0b22f3ce939d6e809c88560a0847c8a51ad8c6ff596a8708cda9ce65190ffe3d24b457fb29c88f670803dbdf7042f8a07a2cecf2e8711f639e561b84aa9357a6c403174e942a05919b4533e28ba1f4a9724c1455a82fad68762ca8ea8ee25a024961d1991b2e4a5587d2f48a61b00b348b059a44a41e44498dbcb2026ab577083a10ec5a527e27047c3adabde815555d16cd092ed86c26863145c296c9523de0286328bcc16ffc27d7a2e5bed590d20b77b51fc2d5646ddcd385f79d03e63ac83b7522f01fd1a9b5a7307b5d6783006e935465da875df5d53ce648b0f570f5646e607ca5d226e2fe06451cef35e687056aabfa25834f69275634d2e223b2814848eba21eddd175c895f66edeb9a59f4d303c873236fdb5c5551dac07f5693117c93827201b56109c398a490136d67501eefe48ba2dcc0e0dca3e7bb099182aeb71a5833a258985035d8b19afc76b622daf4f5a441387f069a6ca00f4077d22e666e32a9953b34384b950ff2a9f4759aaffc066bab54d6988cfb35636f2568e76ecd41bc6823054c733dcee6ab65870de742a4d61af0fcd5abd5210c40463faa984a27c9e731dd994657274e3fcf55c436b8a956fe21203cbce1ec1ba965a8e43f5580f9aa4dbbdab65564dbcd86b1b28fe0033ce376049223b08bbbac9857b5104cecc681a8003c40295b69e0ea73acd0252dff155ad4340bb95b9ddb0afc97f2cca3fc70052b2ff327cb4fe8aa6bda893ba30d2be86b2430f7a99dfe1634b98ab67327d50c366369afacb1c842ffd41273db7510e07ccf8c062aee290095b3ed299eeebc585c2bf2dccc9fc3fed5cb80bcf8a6576e67ee732979d3d82d0619aa0f0280cdf50601ab7a6e3e3a0f62f24a704e6252293d0f2c343b2cbb4f3e988b6309a287eb4a3943290b9c82f6ea93768dfe50a8d51313443ce3444e4b99790964b7282c49cb98ce2c28c254b0d508677dc2e2f44de41ea0428a5ebc125e7cfb3034247bffeb234df2910b7dba0f4df808c1edb42e9234a1be15735f0928f05880ef8ff25e7c03393a2edee2828b374ae0baf1a63d266fee71db913fe4b404de35e28e1584ae938f9578c5b06799da2ec43803980f77850f4a557892dafa4708eb4d933510770c40db4dcb7ba4f8d9138d78a2799662990fbd6142cee38b7cfe9f7d39ed50b4327ff111eca523714a06c642afb2406299362d16472cc49b9d01a6e0a38880b447f3903aeefbf5a920145143d559e623ccd860432121b5b0161a43d8fb8280ac4e7320a412e36053f78feb287ef0af32e1fe5a1c1e9bdb6497e7a4ef9fb4f0a2a9983f40f66c5db8ad972e422e2098cda4955812c09e649842636b6cbeb0e29a50260078e3505b1235471df74e2e737588078d8641af48c1ac39cf05632f80c99836b0935cc15fd80f3fe9e941e68c3fddc8df1cd641722288a20efcbb09620f0376414f34e380e13cb09b43b105b3a22a4f54518cf28cd644830bcb267d18793542026a1258f8e3ec4920ff798152e054444183ca5621222006aa18dd9e42619bfe90f35634967cbed9de93722d38d8011a5efca178c6314a43f12798f150fa2aa9bc9c2baea30008bd61e1bf257144b67a704bd43823b3e06f6e251819ceeb264383caeb49b1d7180aeb56dcc735a09c0eacb926bb4407f4ad016346bb9f68624087a22f50d5ef91521f3ca8a68906e56761c37a5f001b0b2120ce86d1fdd86a2f795086c1e63300ef953dc5f94264350762780f703f89100653a83f9e80e3327d6886f85a6fb4a68c22c114dd54da899008347f08c7ed6064da26dfc8f9250db0d33263bb5abc997a949d845af963f3cd51cf4240b6c2ef3af3d0bfa3938bb5f48f0562a06ca59b662d726317a8c02ab28395c3ef958e06816ca972792c6fbc051123c1564e65c9fe5e13a8e91621773694fccfd4692d4d35a27f6e2412b49804ce472672692c636f3dc22a2a6fc050cf9895af34a33851ac37ac2e7a2e42d401088f119be6d66bf6ad4b7c9be4b65937c34137924b5f9b789d93f598c5162c500c09e8ec2e4ccb47cfd919fee8671239a3159534ffd44711f515286f4c5f043c02b94727832f41862abad03eb0a2dafd8ca9b766ae254b1568b75cb65d8491b488dffbc6e5daab4f6b2910a18b0139af77f10137026116db1c75bb206cea39c2eee4a760a37187dcfc9a3bfb67a7688190d5b408b8f93404f22bce4dcb1eb2443ea95a12495f9881e303ab7491056c1bef4ee4de242fb2aba8ffc4210d9290a291549804f308d1f1e79453b8eef08b7e94f306c9350263c2c3fdf9288e6b77b74308548bcdcaacd999b72998e6f43b037aa19746c92964ec170d8f4c45c9e276cfb38090287a1fea8c2a3de69f246f66bd1ee6d99bef25d817136aff0518584c04103eb4baa1b0c13a09f53a5470ca0d3bf811f78524f8bb1059a6ae908959015917ee1d6c458067b0238125eccc3870465fc8dd6fce667dac35c3395f2f99d9412478f69286176f842c12480ac3c1f10e17327ff41a9c9f3ca25b1df71746e38d495aa39278edf66784200e41939aca3a5c6b30133fd34648cbe9e05d7f8203c4ed349f61b06898dfb59472a50c5065ffa3ebdcea251b37fddbbb1638b7b7abc392defd6d8c2a623b5f8c6b2af21837e4dbfa31049262a89c6dfb0df74d4236c231cab14926955bd861", - "priv": "a5bdf0f8455f85cc9f37da908e52a9f70dac2c1473306439e4f3051e897673f586d92ed7533389c0202df540751374583c97b825c4370216af4ab36dde304d43d0daca16c3f5087918eb0ac74d767f421fe3d1fbc7eaa3aaccbd5cb5d09f333cf4b78f53c71c613696dcf9dcaef19b3c1ee2efaf0d828521a6ce01ffa7f61a9348527342744071064226038054116606320141710221271257486326667037121338804027786413333762444565247120260711112481538554528818355348570835703121724850217680085831247330511727221071532777537181252433162511266101870334182868555603545033287523215207404240325534605842331807636112112578123748213488427847140378435253062845364733136513038331863665164167881816537665065848863257260565026575136330876105673463618643727206285030703671806436818322112274163527184354571804314504110461483305276281527585556577604221866560252247227633024375431035511576001826578516576032642038878266403868054841663872067833221181722456668288121320355140013335216064378035186542241363324612723361344715333431546685723672037350475440828822807350518723244126165140441743684004218174044766245273324152220377505024108077250427538553813160114380427476282474087652860170448374247256182540047212386666433380053013860147850648461451277375447570165767818683367627182818503143056367684131733603212447465727282433537555073853150367373683784851317615160568487055012186553755658442635833444503161210303854541265435850086145313831714057147057120854520605228538737665130427538038232223511606506354232283180315487066067657113311376130525682787352874263703354678684763224515801735756766354734254556702053117703010838153428847256422882168222781354461343605223116617002218761072342227774472342364510245075075620557536146654153377441306448752117273127761641170377382766582167256065853886542021656228353632167205880115560215680560306250271500428858201477207883872516256244502862366650053734802237606638246801357641266043847685428523576470862427772605087355417711178011230254130776185056386880131707363610348377857813822161177008735870862408816363434033522876874245827032130687514032517084000404550331071880041411855515353347350748833163660475436163376714460516374334807032470377016148566161642212524742565118144158720586251383718220750427038855211255848338323237278850416582248665388024224073714504355652603153613411853445800308877122483607514485078628638685574852023328770115826675755280543602581333212557321868322175661562521048051805784217422803480451341517247206525267651220578854840124507450130330783180120225057375467878261257470561528834570641813282421264533224140164101541355026886165283383701241282521170736675535341222832655883108544384278163414862621416360817830726530353375153418874861316345662582058367316632462543274165056545780126454850320726117724140462523727278438211532634765078536860488641558502057617183425565211328306367418664731407825108631866633714182740052163310713218483574715351876351327521183865501355706182848758085863563015436623450348571177625576370888877313167468486714351112267202247833152524060633413850751063367135630834183838550563386607380546701865460634035501871746162676710175335260356668310562162041187655378322137251758003287138288249a1a4563679824ea12950b80f31653b5ef7bebc201e938eae950102a93b46e11f5123313957ebace11d440bdc9459d1b9cdd345863d81f2fed1c4b534d0f17e0908f1fde10c037fafac1e0fc865b74d15d41e1211ec7aa0ef69f87fd0f8f9cc42b0e0e827570776232d4ed86a84d1f7a2201b2f29b6bec81a3238da71a1ac6667af0a3f35124133c5f3f10d7f5faeb27ddfe82b59c85d4ee7340f84787d4ea738d16861e4e66238c4873957d0eddca68f884b726e10af47e431dc904ee034f9f491208466eb6168fe6b399e5ed34e118a77dea15bfd11de8a531c8c25f4f73f8a35282e32094f291308b6ef60dbf7b54ca3b0f5386ad179da593bb9c2b7a2461c2b7c1713231a1769f03fc1b2c7c152af80809453eb6e97c8b4149a04626c93e150ef3dcc298c13a439cdb871893cf3456b9a59fdcdd6e5a873bae7e5c778c99605ec7b01339d8882dee88b7de879bf3ac89910c00f99ef2e8dcfa2eb7d8fa6b5555685ea2b5350bf55633c0aeb1f244c1026e62c82a5685757d3446b756d9acf6c049a18ec4c9359b4db246d9b455016821ef4c598bbf834dd6ff82a494531bb5e0a533f225d068a1ac496ae8d28f08da00dcb8209bd40cbb0cfed32241ffa1c33275a2565d1cc24d3a6baab228c2d8764680a105a834b36c18a9d522d0a25eb34fe00b32193dc9f976b0a23cb220a6799e4d596efd98a71ebe0454e25e93e233191d14a78b5db29d4cfa2435ce41b13404a2324517f0efd5b59f714889c66db5327045da45c38e3dc4d8aa433e1962f9313aeca58b3122b437f0ca17b09414efd52eec5e2f94de8ca5079cc79f1a11e7f968844f8da1cca85d9af2759a3fd75a9ec44be6857b403c88e69f1a9a66764ce7f92e622d963e8ade4bd4973d739fb946ecedd9bd829d5bcf02fb87e25decd98c8ec507eb5fcee4a0aaf62970a6c4f4d66fb4bf7ff735391a27df24b848e93b4e1cedc8b77497a8edb73a3c9aa8b4ebd9443235261c2dcbdf5606de190c35ad76494dda71e9dd8eb70deb2649cb944a60f50f38c4b6ec1e64e12f029d1e0a2d619e4e783be3ae5a06fc4a355511f177411cbe64395af69f744773572b5073fc1beb8797d0508204b3658ef87c62d94eb85e991d2c7a4cd02df7d64b6587102d4fa321d961af7116cb37e62cf3b1ad0c3ffd9d9401f175a359d69db9e86ee9a4255f1574bfbe38a18e94bf0536125045c20921d10ceff864a3a583c5cfaedc1151cdbc4c31043a8763ab3714f942da758d352cb03ad534ebc81764d21285b10e0e0afc28cfe72a84103444a2d1dd6ce6d7964fcb66242f08b36623800e34510da71f518c941eb8452c1bd29d0f6a575c7551d2a208cb579f05e9f94aab26afe4c7484e86cd05b41bc669b7a1ea0db9e9f581528d5c29b0a684766e7881e46625af5d0a37ba1d50bf3f90fe08697b20c7a205362943282350e1747a7b91cd9d0358f2101f5759d81533ff5b83190bff33443f6c73a0d3ca0babcb4a7de4832dd9dcf2a144690f6daf40431c7f9fe41944e4d168474700c8af6ee39668fe2ada2f8b9f015314eb7c230ec3c21229eb886d37f17f9457233c055a7f4504999521ef38cc8b4183088b52cd9a8246107c46108586d8ac5ebaca4072d8639aea5743086b46553e10a6803bd86b494ce06d7fe6aea812946d6b939a315f7e200a7dfe2571caaf009c909fcb75938e421cd542507f50de26f813b41d10e67e4b5756e8412e272715764c1c097d27434e2d2ccce49e6a4477ce65008ebb1365865abd4f709129e7e045368e8ddb80ecb4180ebf5705f53551e2250978c21874fce6069d4a5a51c2dd54a2d61e189aac9247ddd58dfae54edb816a5895959e1bde574b0316363658b71ca5a3b859212799dc9d1b1ee75a8163d16263d7024d03f76ffaa106e7cabda18b5f943f39b420486e45fea2714914421c79d4315bdadc6fc2a77da76d2099c28d59d865850152588f33837a06e33323263adfc75705c1ef5e0e6703999e3dafb419ba86ed5ce3486d6655d6e320c3d43d98e4fccd31e28cc2f51b524414562ae41647f16ef6aa763e354952b44ad5e5576bac79c2dda9bc2361a08bc24697f6a129ce30999a3453b3adda3410dec30ca11edf278b47a6e6f92b0c6670e118ef97138c2d6bfac34b20b11175260994bd93d41fd44b7bbd5eed310b3c13880d095b1a73887288baba953ed922a46a42450d377dc23495707a35510ea3d0ab741be55e1107a439f136bc7e1d03b75e733fd6aa3236f379c7825fd5401d1217003c11c422ca7db8a8ae40cdffa642f76544cff87385e7e45fae6e68347d45a2e32fe15a25db579642b488c05d3bbf597de46ce67db5eed0ec59641ed85281d5e2cafb15a43744b3b60dbbcee50990da608da0652aae2eb1cababb36fe42c414db0689112a37df8cbe831b236967497f4fa17ac452b2bd8935211fb423d415fa916058e45cf7ad447f3f19660ea9a069c447d14603b23be2c6722a581661798a1d9348ee1cbe235243645b20a6f0584621f460d3bab447520372f041684942c76c7cb510de9258bcaefef8ff3b7c3aab4d9c4f3fdc9952f1e4b3a232ebba94fea8dfe75500fd89221b7339a3c61cf0b44cc36cc17e5339137a5fc7265438d76adba37465e9e30e858b5c9b4b162b4769ee7ec9a2d2090b1d5cf77a86fdf7f7ab76b15988703454ff678aff7e7d221f2a3a5e984739c214bed903a842b4da9f29e26e820a2d70ef0217c544a930a8c2150ff41d6f1450df4ba0c81ad2f6aeb54bd5f82612b11dd9717112f424df4c3f27006b37a51407b133110d0c827640468b287b8d41abb6693d7a041892dde1d494ce08ed493c59c68e207a281f953edd91b978d31f459ddd6bb9ac2ce212c5bf3b15457287e4b95347a1afb976733bc848a709900a08fcaa732f6558bd818920509933e915ec76cfab7ee55821c56804ff8322c246cd2d14b66241d0d88f1670124b5e48fc5744e4df74f5ea51ce9fee5c5abd4523d88b98b12e0bef3ec7ca3aae48b7c3c311a8840d593f74134cc0d4d6244051ae18c44e5308b3a997711735b438aa4d2409481da436a84664d64be7f941dca6c4db2724e7f1fed95d4fcab4960eccf7a478b6f6ab5c7674e01867d6dcd3bba6d51747c19b94a4f0039226b658bee299f23388fb5e7a71493ef7c2016754d020825616b2f4810fc765a67876f979e73dff831f0abe6569afeb611ca67997253730b44979ffbf105f0a06d6fb360be8877c111d6d0fdb5d2578bd95b34f4408d7d894b8b211ff1f753ff3290e54a9d05c6a5cfbfcba0c9501fb4441a4b9362b1537c589bb27a17113ef54b068b28fb6f74474d6fc5ae8aa7b66b156faf6ae9954f52518ebc897172971bceefaeada9b43e4de8b074ef0d7b47800930d076c6592e859c722960d32355a63db0ed8138baf10db3c235293944153c60f09739df20b96f76a0171c11b8a704ad44b035eb9366567f9b429aa2de76fa9c12d285b53edd61aaa85459eb7951d" - }, - { - "seed": "16759ce55c6741d02efafef5d7521bc0d2b3adb55088f61f0028656ac970c70e", - "pub": "cf27edd0b90ece6104cbc5ab296c0301dab751fe1c6f0648469e74231a5cb309168b20b154baf03e312224727ffd0f08e7775b2b9fbfdaa283e0d6dd20b3f8f0efc52b971f2203b8973d0afef578dad5875142780c13728b3e658f87c1fe077b39c9cd7b7f84f28948250d51d5c3875e58a74dfa7f795c2b0957c6f699127dbd0c2265ec4f9cf0dc6c3d725936b3078acd64b7c6835d5d21fcb9cadab91a3db704958ff70d33c1ff00396fa561a1bc4b4b0d069a71d287fcb1cb90b369c96d88987fd3147ed2838c7c15be066768c48955f3e1166c62a5e3bd3b66151b0291e3e6438a682606e15c04ba8f56bebaab1e7008391765bf0d55c4c9c7e535ae9e01fb3ebc261fac00b483a77537231c532f453e6b6f1f4d0313612b907005c3dca1b733cfe377d4d9ab990dabd1b85c3ec423992cf77667d685c318912cdd91bf31350708fe8f401031e57e06878cbd155bf260ab5910757335e98026b22141460cd14cec795eb5389d025b48c0f2d9c1b19a41d730b508f0c23df59a93c64a7a2eb32658080f546479955c410399390e2273ab80f87f28ac0892d059e46c338177added57900eb14d554a0f807284ca2b1495e6dafb461054b0e6e14e7ff9313d1ee9ff83a32dded566836ccd22b72d6dc6e52a58c7e56ecfaf68133a8b6cfa5f754653ea2f0c5ae9d26c10631b747bb4a452a54ba96f59d339ea45dcbbc0ed32028bf612753aabee62d59a59d1660f88e6d9e2f1679c7e4196075260d45c9c3058961f0be3be6f61d26c30ab6517becbc07fcc4b06b98e7b5fd9d14ec59e7cf89a4c7e1014bd3d157f0ef8dc37139683f21ab04e9ac8c3525554957294009796b80f0e1c05fbd63b3b1acee497dfa493f2559379b3f9a5d94d739ba9ad4214f746f4103f64b0da83f779d2c404ccdbe4672177956f6600de124f820e799f69ef86ea372f49780ededbd17604606971e8a41bee1770a85b7dfea6e6b8b2810e41d8abb894a506e0880079e093978f11f9fedef1cdb4cfc370ca5ba9ce0de73811cddb1e7b2be7840c3378a84ed126cbfc75c209984abe1360de2139acc0363979ee99449b50beff8b48afbafb27c9458c9a914f3a7607a8e8707b3d2b1615097bb80f07d83bab83bd863d46020f49bf08f343daee8f320ac9424d36bbb91f3d7a8d00579b07bb7c53bc700cf771a420abf7c656f9cdd5134b2b0c6fb53c8f93bc5c4a475c11ab043c1b0a50fa5b9fa29d5a1e684f50fe9e2e48b8be54d7dda7b94ef28274ef5b88c3433d60e027383abda44dbd1e0ca737b48aaabe9f98984d30f2dfd50b678741993b8a5b483a2c56e038046b64705e23621bb23870514af33b36911f97d45df2d47db94a4cbfcda78240c77e9f7b99710e5a59a9ec2f5c89da2e9c927cb40c58e562cb0ac1971f92a5bc1eb371da6bd1541662ec4f0f78ff3702ccd723d1b4fc3afdd757b75bb44a5f4dedb9a63a15fe399b6e59928cdfb3342ab4aee2f4db0dfd48c5969f7409a69de1ca6939d9121d119ab00b16f934707d83728916086e22f1e09b80a30e3dda76d1f76dcbf9706b3cd4a3554671d9092e891d14ffd74df0cb8835951d0233bc1068d6d1bd766e487144db791dd5a72cdfb5a39f0c5db47141706925fff615a2605ce1b63792d35197cb9ca7e518f27e65cb32617bf91a07d5d14c186a4cfb7e36abdc8c71d4245b2d70f20b6412d478b36e72cbc2e1d44b23ab09c5b89c4725cfa3ce27c79fc2f7451ddf529183fe7c1e230097dd5aec1f23d3a817ece30f843be07fe76db36fa3447362197e69575719e80588e93e4a57c11ff8aa1d8657e54b1425b6150ffe3bfbef5bddd58b867cebd10db74b4249a0b650e3ac3a65f828582ffc7332f945e82241cfa3d25d731c01fc7601e2f5874983f2d9e9d5aa781287ae5fb25f8d9bcf73ef5576cc46afb1076b95382d89875cc30becc32719098b5bb95fcbd22601930d5a76660b67870f269965f6115e1771d558631002e7388c4761ad4c18dfc07c3b93e7d11257099900a9b6eca8086970b9cd7f0ea9c1fdf0e37ed7f18f79a81efc726780f544f4e4f6c49956ef2a70f56152f030bc73c0ee7c57ae991f7e3362115a029fb411cde0308f2b1add50590d7b6110f161bcec333c5f70a52f6ec186fde7331a5c2ea232f91c7caa5308e79e85993fe7fbc06930ff98aa4356170ae3bb262b22c24f3971b3092ae0c4ef033b752b17db8af26f660c775eec805880e12f0f87d5e1965aabfb1d235d5de332b177427650e0162c7599217184faaded2ca7946f3033bd6dbd59d9b2758386f463d187d97f2cd436e789415eb50d4a567b623a45b3ed8e1e8e03242e7b85cb501c04ba6244ac3010f7fc8047df6f46d2b86662ce0c3c6f3aeeaa5d8ab02fbda8039ee7385c4f139d47f70c5623b2d434a138bd4dcb5b7c40965512ce283cd83b63dd9b1739b19172537c6c50ca6b212117eb2b9f26a94151d473c865e5d860b272872e9113c8399a5a150376ce51ee643918eb0357eb4e785e8ba5ff3259831d63195bf1e21fa81f36d213d7c8bb52b4d9dc17d1c592518b6b97d0bfdc160ccb1c44cc624becc28b49e294f206073185eb1414a4b80b18b376bc1ca498a9873e76a225dd2e8f8535fc267e40bd627f6acc8f94b8a70563e55823775c4c58ee180e3ab69e42164e3778e389dc4a4689132cf41bc3816437b97af05c126d658386dd57159cf61124448fd580f539ddf48fc22b46b103790705a63e0", - "priv": "cf27edd0b90ece6104cbc5ab296c0301dab751fe1c6f0648469e74231a5cb309d14e7ceddc2a30311aa8fa8f33273747d84a4f0d8ee7e194564633aa61e52915d5d8e2dbafde6d3f5d79c3b28ad634ef193197738f18e4a676cfc57cd89cd0aa6f0e234e1ef9628daa5784d6e88dd9bd172917508bd299439586a2c69ec9ee37516408456805453875186164354434762851144032503062044733174535345336243074007370072077081545713763660866431727740068416380203118388213565687636452870788087330528072715111223815614114023416424628572273654761365202371732860200885645176752622184560057533370811066568577508011873252658610003344817466632285818231285557473165208431105636756216358276868345764816338628113787615730106550304583831526218881611205302483650721835183030737847070762778474055733402548878760487075428407073405005144801723170186433372802720438860108856746505547118015547131122453566773381342522407281545850801183484018184666083467106168381252845568124004675454602314541338432622742687024545623154163133642142284145826740831864111748641572426058870067085812666034786330234235402238130001884155852477742051765281745785073343582078116414130602308708382046610771844771422553017257116530515834771623210643083653453123174273203072120652165461603377577853268801105230325786774860038401255212558785474148811005612536620386306604704351810446347070743027613512061524183212465467663737220484528055077682744477361738537607035114778361715572673801101334710201843154010635705268423258373218118673778880168467346108724815012616873216832455740487844547741518240111500865103473675713041381803575311157872410255701424078321127582473648431113027582351430662278746751035665641182434584325772861215525770615370625335026857551177161702753358126622760777226647078220754285585438101185067104306615265684566031171156370644844601446724773223546111143485217226474815348070603068162168730827730621315400104575240651321414881564033855112770221780800225157528348444266604837745836675662685500716522842326213800620274755378763818201620041432256675142301443166263778606832838270748825315058517802584084457456813426874047456608883514726678781223637518532315712014762086217806235541401078781766415284331567726815303634475775271858640741021524306284275220610644874785084105424161267563884428838216142316446781311233544824647208842466574102173038377413542118331143367050032021043212425764087110600105282382455268312103048345414288052540078876487667764823025775566311214818185543787576556256857315236518510021215252482803706248475668860228066666672561867742220301027605488000438235713416236536151436128508016780048467212168013085034575086368465731676561760082315388865064664006463851448257676647715152480874332803114601541422802066821101585027654741377572383658717163467081225212357315441278864346071400588203756538864216143433263515106785455401547748303686407408160384157550870668870806518373802647386257117430103643478524250667688677831215028557767150786248416665782857323615017621284673503646038567228556675312835873622053521367101744308644383425387466430243221642874703241566431377885506752554645704356662457447386007618112165350121803204124113324380005611435572303115406311786186209ce53c40afb0f90429725b870e47031cea4209326358fdae2531b5ce92a42c724ad1d1cff79db6d07f0215e6abf1db5f9303b27cffc420580a0a8612c08e1f54005ef429bc8378f59dbf6a3fafeafa03d9c41edbbc0dad976d8e103cbb49a9dd674bae19e45d44d87bcc9d83e8b6c9d99e4ec4406b744718f49dfbb12932775c82161c63ed883be33fdc9f724b44f2cc2544cf1851237d53303b82a6c8e2381a7b92345530a7740a6a456df5245388726ac8c568c075d849ea225c42187d25f435da2543e3842d46f747400ac1d566cb1763133eaa110b66a72e025082b70845813a7ad6d4d39f017c9e8cb006c11a73c369da6e1e20b6282ecd8d0553cfdc39621890ee0110f0a0cec2fd1220c7dfacb8dde955e336c9536dbdff7600a64e59b113c28c86ce93b035c75e204f0fdeb7362f598475da64251cebd14b95600b39269c6c5fe67462abf76b26363946b3de38f6a3a53c261990a5e147cb12d093016342e57ca38e28736ed4f331ee1a75129386dc2a2d8c49fe616bfc5a321b5650fe51b38ea51776d1eebc454aaa446b1c2ee18c10690aaa7889ef9c2c25fde8e988edfb39273a0d180653488c1c541308305abb2e8c430eb68afabf503dd082d8eae81e196781a735d990cc89e024dd22901c5a3c382960d25b076bd38e01fbfe7173997760adfd97d94c49bbb4848dd24666afe02ae5d592cfd8354ecdc74c1c3bd713355d733e7bf531031491f869d01037ae0336e979f263d7d1217ee11554b90bfe16a103cece88c19fc1d9b5987bd0557ac9d09f07b0ce6c01d2fbdbec726fa5c7712e60f70f1ad4c566733cccfd650df6ed846727d7c3d6c8412843abec36750d8296776123a10a1faad44ee0f19deacf8c7233c8e456d3964e0df8603fe8bc04f73a261e1f37ebd5db516645f4c800186a10fee9d9271b68a0b27ea99bd19ed87e91519f795c6a1a5f7fe26d0b07d9b618cd7153e8b302fbdd7010a03a58817d00f4b9bb5bf8d9f9fbfc5ffb3fada79f1ffda8a028f85fec0a6b74019ee18cb7afd4efcfbb259aa3104545a64b1b6f226a72065e053fddd950096e8a7faff0125b4aa880b78c84d02f00421a72942c7d7e36f3d346b4434703fe26d063dc65ba0a9f15cd05021aefdb4a5ff916ff20bfeb723f90be1517d49c16df4c919e9f46c54a508a9d564cc781c2271dc08086ed0265f60ae93d8bdd7d1a6aab191f3a91a13d7f513a136385d94c83e770972ff7d4602bfb1a95dfc204cc0024cd5ad7ead3b5d464efdee19a01d57ad19ef3e47be36cdf2913c145b77a144c9457841f5a855faeb9470bdc69641edf4a800f20bf88bc5307de87c5a0cdb7114ed6f18d7638ecf577a406110b2c343c6404c5a4a1e235c50e48c81f60ae78a351080122107deb5b3e296919881ef977a12f3d5db6addec4a89e31dc7fcd81f217e31674072c5e199c43a7baca72d697a3093766bab7c2dadc817bb26257d032af358dfbe2cbcfa8c2b87a530323d9eff5709c2ac3358657a51c13c0f8b55bf17ccb04a29359380208ce79f80dc384ede6b501ca27e290e51b02321ac77daba35f297a552e21ad4231298f58c91e56fefca7c66d27bba45acdbf7b63dc48bfa63a0753c47822b39d11d60f4734b81e7fc8895e1adf2b7c4a4574ee9c0f4a829806a4a99841e6f836dbb8d6cb007014005140d2c39da195e9429a23b889acc8223104125c68de0e79ce6886bc06ace7479cc99b3cda6f568fd8a02329055ec10dafa1ae57e09eb6d54a9ee3444b73f38d2e6b8224f7d7b2c80c490c28fafdb2e22a83bad4d75658df39f4372c0b9f1c50d284642c303e5d7f54dfd50b5d097e2f1df300d7b8706461445438fdf83ce2be35e17ce5da9e86a843aa24072f2b20c5377841dca8a45deb6aced51b9c95fbb93b2e4d80274142dd1a20139b7e1da43748f1decab315fecd77f74abc890e6443917052f428fd8a41fc938343a3db5d89338f2af43b84e83d7af389156f88d06fc97658b37b9a6bfb6238108baa40e9c6ed8a348e2ed58faf6ee3d3833e4f0aa517cec9f7d83f5ddf46f88dbdea230f761544e1a10e0e69517e47f94d7230c0c60371e2a99897eb97d7ba3d8b6931fbe0b3849265c65f1e2b8bd120645bb724a0ea60c2cbb6fe46287387610f139cf5fcb6b0bbb32a44ba4c3b705903dd54cf0ee1933f4d7257fdc4331d7ada07fba0b9179faf1fe3c8f4f9b654bc6719ab70f9b36799476ef0c4449f1caebbab550f52041f88f0f4f32a0697fcd0a28b73e26a4d8fbda826a680c37b3006b059363062aa7b04d561d38170b831c47d656af0eb7bc00e25cc423fe75dd89bf7527bff04ca793cfad973706d5acb8c4362b4ecb3deaa59e9acd999137131a1a324fb43d88d9a9670067507fb95fcd80b29e675093145442bb9499428ce0cd635d997924ac4c38c5a21c452e5a399aa1ba6ca0050a0e13cd6c612e9e7282ba21c4dba82f4c65d6a6e0a5d616ae2608c804d463be286f73526e70719ea9dcb16790b31a6ab7087dc60dbc370078bd1c56219cd548bff20163b8568056ec6ddb1eacac12c873dcea792be7b6cfc7d792fd57808fcacc0c32684de298e6eb382c0cc03d6e6aeff28eaa92f028757d27c4809614ae4372293ce517cfafb94d6c49ee963d2b887ce13ee6994e56bf47c7927058d1ff0de5c7dde04f6148f8b0694fb6d99dcc4f84417ef371f76638b4baf8b83cd7810116da648b202ddd928c91b0df5e9d4d1d830afda050397ac882e315f809374c7fcf31d9d011f367f0afe7b0d05fd0330c3ebbf0b5003635d007461b155911d26f93cfe7822b509b7149771979fabc066e73b5b959187fd903c4e0960a5c748358f7cd0a86d44f58b53cb53b37c47558e1253440250d0cedf6e19f9eb8c341dca787e05e1e7be7fe2dc244e2b5f915be5ef2cc789dd77f8816d1d29cdff437f4d6c76bb0f99d395b66ebac0f8bc4414260b5ab7aa5c430b330a4b325a725b709de25bad74d3a08f6f7f76c76001aa207c54a83eddc4368a0585efa3c5439ccf0bdf11f8874ff7a196a1703004714015d28db1bf8a626cea8e9439a0919fe802b5ca19f3a4c1be83f0ed3ebee4a03a3a438de157eed40fbd96c379ccfdab89fa5fbfe123f10d552cbcb3cdc055ac854e52d5198be1c745a79acc57660c22105a786c8e1349ccbd5a7a76f115a7dd98f16308661e2ab3842ab455d11bc3d16658cff8c4e128e36bc8912461f883b29164e984f8808de92ac0aab4cc3c8d966b365312a6b525e421780fe0434facd08e09fc65cc84b8b21e42fa7115bb5a1fe4cf3ff75133bff1a437bf2087f7e31c7d7c3782bb75419db512dffa88297b50c4bb234435a301489a066fbf12a6581f634ea9e219c3805cbb63f9ecf1a47bd4a1e5731cddb28cf8c0c40f8ffc2cf7290503a22f4b118a7abdf6e5fc44c6dfaab37c8e3304a10d601aada7228029397b58df0443c155aa2afcd634e505be5b1cba8eae7373c5a933e429ce58f8c520897a98d6fb3d4a" - }, - { - "seed": "1a1520478204d8ca028fb48efd49367a562f66452e43b305118c85b4444675a8", - "pub": "842770bc8569ef9b4564d078eeb6270114392348de1aa90ff94b56976d15ab3e1836be3233af866b20cc02aaa8d87fcd7fee1326d80ff94e2de3a72ae84af0fd92016765bf45634b405decc316b73502e31674f8fee147801679dbe2fac60774795788b5125266762e8bcb71ab672119ccbed4ee4c5dc5429d98a6a6aa102a79f245752044f2c74992b08329d30a6b51a12a9b5b36cd00dddfdb5daee56eef87cf31cfb0bfbf4c51f1150df8209a85231b9f3a22e12f64f27afacbaa0141207d452c53e0ccdbc6cc09f3b4a2f1264500668971383ae96441fe2c4ed0dcaa91ed7c2452f1826efeb2421bb1b336c7707b6bf68f8bc603ca56883e437b5075dede9b50c094a51c6e47b3d06fb25f5369480ae7bee9c3d9635d684e563c50329e1d32a6cab3aa491b53e6d48bea9c140c14be3ac917475ed7fda2593883b6eb71c950651f2a82d16f446b58cae9709c700c2ab622d824a425785da8799fbf875cffbb5f55af583378d624df7b21a97a241130c0f18ea8b4921fc70542ce3db20e6730fdf6629566e2656f84b4c96e6f021270a248e31e9b718b08b47d2c42558793e148ff4548a09a091592f6a57d8d0242a8c2b0eb3efa26e477d9b530d091eb884b2b720d9de025d9c0d0e4ce5961cf59c550bf62fcd7bd659a3631159c2f0ff4db34e64a2c3e13b6d48ef5e420444b95655a0eeccf6a8e898305d6c9c117f4edb5772415c0a005a1ca40be58fba18059bb10e25e2f483e3b58b2c59ea4794a07b493555ad4a555fc253c8019af81db432ab4624a59c4004a9bdee75c91cc41a20401965babc0c55992f87f538f9abb80ea4c91ccc954a3e2bfcdffbe8d22b9754c8535f0f642810b2dd2ed3ecbb2bdec3243e6d1ce1b489bf6c0be50b8316d0045fff424f49961157bf6853e1f902a3b118dd650c529c603e9438463204f7da7f489ce50f7a77157346affe9be973dca0ae076b2df85aadb46dddb57302f92c28bb77890a0f50b9d74e12afbe40fb386d08b394af62ad94c0538aa7a77a7422167604e9aa9cc7c08b443a25f850b093aae707d883fccad208b7d991a9c0465befea4865b6a267427a7f2d02861edd8bd6e72962eaa6d2578fd45a27036f5e9eb6631ef5abe2084aac7afe8930df7834f4b13dccefaf45a632e7783852cfe5ffff87ed126155d3ee0d40ca5f2e76e1bf47fa91bc450602584301a7e8b20e78da1290aa8700bc6f0863053d0558a35da679286cc974bad7337ff1b8bd169cdd3c15a17acc02201d536869c6fb56ad8d3cc0e3bc86816e94a7c07f220d03a12c86b77c13fe2f03f455a5eb3339fc709db02f89ded1d43967495c75de8fb8a4f37f458159842fd69c3e1aff691c3fdba87027603d5b99b2ecaf26752a115b0ad623cb527a82f6aeea016f75fa381b2325c7bc4370357c2d53fc27bd2dbb6b81fe1522533016861f1deb34b78f3f76e12d30f4c674ffd86ef1607309abb3f015a9e81e4e292f41ef0fdd97e81565c546e4a8a2336408a1e6f7a7bf878f352338e18a428fac3cfc7df4f9013678cdbceb12fdbda4fac1144dfd42cfec6ebd951555698732835b701b6895c0383ce71b07adf320893c7cf3a50f3d067eb9bfe93f4994388ddd99928eff959c6c1a78b3474f8311938f6d8e488bb45cc72fecaa84224e5a9d9693fcd8486f78385b81dc192b2126e8729dfa640ceff389cbd01304801b56b23e3cd64f32982ec8aeaf6d1bf875b97a07ce44f342fd351188e9798e59eaf1bb3f80b710d732992323780edef912cd529391adb9c4c7900a3b5d34cad48c14c49ac3ce951ea8db4e944e8ddd5e83bb2ee3444b165c56fb6da01f5ca9be7a7d2ff84b085d8939b3b17c6ddb32d117e1b0aff70c9b6c7fc29264a709a92b216b8c62c29434c876a12f7f44f1d27d58f7a5f7707b6ce80a538d05c40fd23572b9aa2df9c6c271296e0a6d9078f42baef55c62809e8fd044c898873edd2299216571f832ddb7c5df718c4270adbacf6d5eb3c5390418f561a2ecb4cf28e24a082387cc373c3a59ce2fb294e1e547be587e65d8045a1ad8f58936fb2bb7776cdc4794e40a11dbb22b9ee9fb06aef118fb9a72a7b710c1aeb4761034bf4af7042989b600b4ec8d6dce81184b2d6fc27fd97ba2eca40ea85fe3006566be60ce8674ceeb9493323ab6561feabe98373fd7b45674c8161b16f147001b1a2ff74dc51a0a15ac87f3ce086ba134bc3579feb31625c07f698533badd414e9a8cd0dbd21e0678e2ecd7356609ffd4e96ed65c3bb6e917c6911477986665bc9d3bc2ffd480b5624c143e09ffcf5ea8433411de214990bb6a452391c1586c37d6aff7941b686d564aebbaec3f704e4ef03968999efe95493368853458a40266cb1b1f1c3e0249d816cff02c42980a73cafcd929aa9536d8af31b5f9afd0e323c3e174aeba0ea50f9db0fc04e270edc19249d65af12a09f133a02913388b386aa897a7d4f4bdcd3f90b3282fb48db6ebbfb21257644df17c58e57a150e36f78f802cb0f05fca557d5a77821cc74a0b5d9f76e0d5a9b63aeaffa3869ef79cf2f2a139cb07e245e9a5ae90037fbce24ce4b076d4795224c2aa886e423785e0e9b014d4a7ffb688bda6219de7cce223762ebc9a48830a4b935d0f4d9768f84f7247e896015063aaafc1a613f575458043420e2e5650043d230f06b6a78d093b660a26573a645c1bdc900a01b8cff95bcf5a2db23a69a69179681f550e04c324a48bc52e92da43ee0", - "priv": "842770bc8569ef9b4564d078eeb6270114392348de1aa90ff94b56976d15ab3e71c7a10c110a218599985787ff89f74bc94f14ceed203c92f76b5d67c5b8b6796b86718be88a979951e9af1ecc344fb99232411f87888f3fbe77fefb6626dcf784db0c7ec04a3261153e64729255e5ce6b894cbb1085a600e4bb0b03317f8886231702201058730723376188778513655812720172542417247143646428467073443314821558505445472081234686830274636170123228128315700625348670708056866251602156687542664438717868470378622443800377346336674542226381071034445030257183710411707658015133175365315628308222508432565388880836567878400317604235388313286765740235347182434457158814480762440746180380258134310686500677042318457626156280488882282674122811574762127248672012054076701118281460302420147013883802514645737522146600613056240136251846755266808132084387728784208687387732824316004177161457846583175562587327431712865534241213236603884536300716533078315626426655820641212230038185751644338668423426326635871105864138063716425330034814786417767388845064650681757471566615121140773133884856204744373720784387445647085255465817762845160020133010878367040062383084562467661733017263525738783274220670582858510453422721212564255311404704722055575627231518700445822334550788684185480667112556485545130470664356488815156248663062318887582478736241505814413368843465478500161842054157741700704620375746677448687646640465602446038662064506232040688488545875504681671327453411777175183001230743263842058632518307126387382745311055143874741412652558685470007145300836667478266765746720400414877053756562543853638554022055767416327752773186204257730441432226483061516523786268418417712485468645471672265731856455178786356443681803602068235327538110083351515556343615860803101225335447663035673464647078555401071381357720555132331165637465300650732644127750530363550200566217756741351568334658823132266106657664531167085175005811475037652261325817387606338288620565380266463665550880676743051820742216586384231472841757814014150130847064753035562530164461378674013218167481421451275114210804288236311323672003873724375163251155154108303660515386682522367768687520216231844201453516302058387034720361772125260457738774237645072531304857314868085873347454730385585338757726430656643873504153136638132646508716410685703137771500478115462036447706678642871630833317150172751226273671655845870784214880067160103258382278756008163457685251154205335015838270738631741007511261313311742713137207824551084847527852768414008530840523524707832357752407838621837744764534808245473201313077736628712454463573282036047606177628356273553851122846857773665077638871445056113471408877065460343677241566065401740402885336200350816455438826025210267242615477370212156817586755010774300244226438052721318725583862702644650137844613448618726312407205277538504854674606264472087585650666470602431007157683533714105566221537353610384157440670683218006615808544110058801184806484305030012037257405731613708843171027163255001108804531421323638770136218052673025686322362266664828487564412206143775215655602403825841434121722386033731087561201120571426628221551541811228681254526288715703202548412644ddc673fe876bf31b6d62aa38b221921675ebfca9aa50d8c0717d3ff935281266a40b58d839659d70d618af9961c2f09dfef7fffd9dc74fabdcba2becc333feb52599a3f8b570e6dda5fd6fe6502b04c560a1cd59ae5c67efed02291fe2a2b190c226efb19d5871371d5de58883d163437507226f54e01aa46ad228f395ab023f66a866ae5da63d9df0b66314b5223802b27df610449449a29851565467c348740d53d1ed8e4e0c36a4f422079704c39702ca65ab322a370379733ac070c30badb277e629cae8175504ec40f52c12d6c6b2b0cd641158cff4526973827ad68d7729e26a56dfaff82831d8eecc3dc1b296e2956c7f7848cd3c70fd67f4ac16405aaab4d4c78a1fcf2646d7f763d6f295f0d35095c4a3a2e83a86ca83d9e24ea38ee2c8667804aa73d369c5fa0eb148abd763d5e04e16d7179343fde380715f87b2f5c1d96ca406d412e0371b9c5662bfac94821d3fb1246fcb77a7fa9232c9f3972b0484daf748ce475ac1fb2339686348b6bc674fb7ed3e4e6a6c92a480c839d153be71aa61b23dc004e22d7d1c6e1bb696565dea94cd434e458d3580e1847da39bb228d13822695850c73464ee3e88c9209acb603f2097504ffe662b0b20b8b27138dd27e0b338a37045a93da327d7ec4f28bbec8415cd0a5be2d0a95c67de588a539521c11fe14346fd714f4b51f07cb6e7cf466f8b1d979a2362e08f1f49f5621d6ac52917151e61abadb7e2bfc10a6cc96664cc0335bdae35df198cc44ed61b282b69c7a1b3fb71dee7b3e053b7193170a768601978dd4a8db92805e3c8778ad770cb7d94098e4eb999c16f4fe59552a3073c194251179a81bf3bdfb6547da36d70f46faf467bb216da5074e8fe7ab595d495a20fc5a0210d6d0d660da3f716ea06be4c56cff576ccc2328edaa460e37103a7b03ed2a867b1a454a9c667c1d01f132f2348acd9b8a7c4b18fb1a2c64c2eb54e3ec265c864b922ac2b1aab30e7125e5f6ec16f37d63c720bb320c40b12a39e4259c9fda98c37eceb212714055e0be07f85e39fc4679b9f7dd1ff402e7e6f97cacb1d2548e8c469c0eb5c25a98693aa70813bba53b351463fffd5801af39e58f8490665d4133ef03fe83ed3b6aab0e2becf0ba18a66b6401308fdf1720d03005a94b4c2e319bd76ac95ababacf9b26ea783a231b444cecbc8c55ce98a038983be9439158feacc518cd113c27de1f901e43bc060d7a32af33224639dc2a2a0ccc60b31721f44961dd64b81e1ec48852d0cc0a784b23179ef02bfe135790ab578b473f95eba1679e48679c0ef848daeeffda4c1310f0bc23e4ab154de62fa80727341622e0e77062f52d4586bdf4af660d067727ebb7b050fecb835f2c6ab3d2c8d758aa6ec45ac79845c62f92759306fd1d9b97411a1907be21ef244651a9b22f196e59f21567f9988c8021b85b7c981e60105f725af1089719f039f6eb31fde133e783f085cd5683c22ee3e70a5c0593c500cef37888797874df0a3df2440f1f8898253d477cb53431dd42ddd25db96cd6193af62c6e3b69eb0c73bc449bd7ced979451937249c05502bd32ce73818794484190d3570d3c3495a46144884e1d0683266eee8857aba5853bbb5a0f222815eef93b2f471d2054727238f19383d29827ff65a093e1efb0b14141ce90391e8a6cb166f200b6c763dc6fe3e5a1beea03de341277465f89d78fc1399bc92d4ea0d5d62cebcf1876bf37a137b8229cf0183c835fe9dfa73b7239e6342d0078a247908eaf1252a1065a60cfceb37492e9f524cc408607ea865b361da0ad206e2c9d4d4ccdff50f9f63d3706c9163b1055693ef2d9bde961ba85994c304047eeca80646fd81f8fd46cc44863457daa860efde929a491989c80e6adfc794850eef0a0c01d343974c407dd514cc66050bd439f9053f663c4b4cc486f3f11973c161e532e5d8e9aee1cefde8e5cbe1a80d1d8c436544aeed490a664fd8f91b6fba3077334637fea2e549e64281f306178f9e1a8f56ecd758f95f94dc952e38d78f92837b99472a13f677e6b5af3ef6a6ce2e9aa54c622941cf98f938d79b78355f3ac80cfcd0647c0c1e1dbb4b04f5688e1d5e0f4d30655c85515dfcb1c49ea1dd2d7fd441b7845e60369a9d73ff79db6c183ce9af44265b450f076e73d089d8ac083d237cdba4a715d33f03e8ead25b4120148b36c63f2296d9db09d017c946a265cdcad3263e72deb0473eced20e9e3fde02cd2defc2a166978ee2b01e4ec75f1a32e96b24958f1da8f0a3193f6e0200f4afd59ed941909ef3d5d041b1d1aa1b1ed79280a82604aac11f8ea04eb14eb8b0d4a06faf2fc99d2a5ccbc5a759500cf648a1a67a60f10cc7cd0b6b5a4bccbc7622d9ecd7ff83e1599343a22085bb4a11da0446b22c668078d5211f5de6ead9272165a631bba60fcabfede47aaec562970dc24f7946c279bc0e9312dc6b74bfd311e24c18fbd011d59853967db754b17ff0af52f6f1b602eb0df2c2880e47ec87dca35aa46f7e6604d2bfcbf71166ef6160ed38c70ac14aeb97e39fb97692b118a6e18b692ff6ab91d196a4e718c60c2558cb5cb658ad4e5ffbd90278b3169512b5eb12fcbf21563249699c8f2df7bee98264901605c1820e1dac4d6d626f4c5cc06a05cd6dfcb538b06c0634f5e147f555cc54ba7af371f70978fa3501f069c481f43933a979822d2a79104c1deaaa9363a520475e2ccf6321f0f123e3afcffee327a0f59883c17fc1d3eb5fe330af9e981a3b895a78fb31fabc1091575e189705b0b27b04e05eb9ea6d05a6aa7c6d32436ad27ad9f4096dfc6ebb2e85d4449e308835a4b49349ef96b0ac82ccc6730e1429af80dd8d5e0b84bf3f841ed609e898f906e1b09753fa0e0a5af43952c84b400d6ef09f7cfb78c430d6bab17ffcecca98debc078236fb65944ae95b34ca33d7ab27dbaabf52ecb3123a8278c2142ff7dc357fb491d7bddcd3ca4284d949d1efe905f02a01dd44620a9a0112cb78214057f6f0711755814ee3c596efd7230824bdbab540445010ad16ddf5fa0efc4b5d90f2ac2f57cb1f88515a9977724c643737b472619278bc747bce1877c041fa8bd3027b56d7f4c826b75681bb146e2d42c4e8f205ee779929d74c419b1a309b9b53a2f7100355894cbe365561ff62fe3f0f0e9079b37bfc52e1198dd26471b7a6450af9fa64dc9a070612c1650c9805d3f7336beef26fbe686a9a5314e0ebbe82e5f80c6d596d145b9b3840063a7fbc04d3a2945b483ca721b90ca75dbc79191a1fcdedddb499a96a0737556a2b6ef536653632a92fae2c6106f069ff829f2ccf8fce667ae7d617c9f245aaa18b60a57103f6aeb0e225971aebf3d9a5d63866502db16cce4326c5b544b604145ee44522988614a6f92ac10fda5d064413eed3b14cd9d410ba73fd59599c59475201044982dc6617af7a00010f99614272b18cacf644be0126c1840add2abc4d20cbf39212379be93c6af8b1978e69c41c514ff528b6e3baede9e8817c479ead" - }, - { - "seed": "c2b63699d7c013e2d0c3a6a5d79cb60122b8c8574694975f4d703d75035ddd6d", - "pub": "919f02200622095e1406b0d36b1a90a3702302ad0637553809b0a3b8fd3b1dcd170667cd085153d0943cd38a3d1dbf3d912ff53fbe702635789c4dae8f6bc6750483d1554e30ab38ac6c796b7e838b39cee22570048ba090bdad7a851c95bbe48a564fef34d9f72c88bd7223add4ffb1577f0a24fd5de75289710830695932fc0f619a7e0e41b26436e26f277c8c1a6320460444ee13363a353c003b8d4dec547fb6b5d054382927984e791c9a718566aa78c04c744fc587ad18f55157d269554a5ebc1fe0a876fa2b1ed8baa686625a99de374b93b300ea39571116a9f7c82aa6b96cfd98f8891ccd2b7b8854c3ec1145d9a069f0bcf0d34f9dbcde3db51b2e87aafed50e92f8d4ded20c5f7986bc99c0a0780aca994d56d867a10890be4a89548be3e790fe52951af0860fe66b8665802d9da9aaf1f32b2e37cb3ca788a11f842c851ad20dba6ebcd90cd27377fe75d3972a07fbb99cab3ed4ef317b6a43df763a70a5f6c23b5c5ee6e0f104efb6c57b338facae6c0c437efc90d5ba12c0146ca119284686d863b5b35470e620025ad064673c0cee9839d9e047b78450c4882bbd36fa17e4dde53afcca9527ee9f3b1a5a99c65128ec41f3ece1b3782c20ab53f2860f472c31d04206ae73e8c9a43ae565df540cdfac9b7b267723d324678d11bc421f3d724cd2439762ca45e0e66e06df3fd2d218cb2b35848806881266e3af9685fb1487d81b39ea53a90f449693f7d4c942255b3621af43b46e928e0ccc4052432d1066afb4d03c6bc118740a2056044896a2c6460d0fefd7e5c9e19b2426bc4423de45f9f698bd5a803178aade9aabf9d3e9a01377c299820c4f61a2341fa1bc5321ff5e80f9d1a99d7475c8b78b851da80167ab21b815d4ee09fd51a2c7fe400914d2fcb2455aa43b96154b27d6164d0a48ae97f5af447444a15f0228d31c2655241c98aac48719eeed2dfe0a766c6e199699db26ca099bf1943359d8ae608576d33937992a268cf6490755d79c1b6a14f494c2cad7fa3908f9222c786e4776ab984bb7f77b0c892d806c867efbda69ff21bf473223067ff55913bc844c2ca71790428bc00eee3d60f1add02ed9e27c631d3ffc6ab6a0d381db59a82bd9c0fb751aa0aa3e12399c0b04195a852ea5294c27a31d9080b0565812f829a8e9f4d112e29acc735152fbe32db5a47a9b519b01d392bb1da7c9a856e3cd9b1f9f462f8990c7668f289f7b03fa92f443bf11a4494e18582b0a778548d193810effcb0ddbcbe9dd02683b9a9bb231187d5955e04af986a3448de0a377887e987f7baeb025eb273739eb77e88db7b7855444c6ccf9f6343f30ad4d53d7b2a4923265292db0d1d0bf85ab199d7a6fe544541b66544cbeba4518ba5f47a7264ff66cfa2ba8874135b4eb23e094a61a1d3afc3ce418ca9cf97a4b08c512c6c1b6b50fd6b393c278405aa5091b54f12b576fe0499369e90ba685ea7d5af915485f5a93a721a342d999c985fc32c6e2d1e43d4ce319a8c907874b807182b5e0f0794338e851b21543ecde72080fa348ff7cb9855819f905880c9de0081b149b9d74169d0881c37e89e4874e6d8d665bac4dec61d3200f4c7b88cad336449e0b2ff4e46961685645347280be9ec144ecfb60441a3249ce8c9444ed17bda3803f075660ad88296db499c54c17934dfb76e1b1557d03bb14106960a0f2357832b314478f694eae1829d53cf696a7200aa667d488c85d4cd25a4669abb2f69b3caa7382f99a1a73e75c48994d00ce8a9e844e4a9d74301f8138a765b48980ba5605221c3646867a19a02d3060aed73858bbb4db5b21fd9c03bc670a61774cd447f55da763001d56b5121fa9af4ab04e7caba5a34fa17a40a696e11c40fcd4c9091a61006d7a0790f0384abcb8ec3a00c882bfa11058cff423e43e0645d20f5603d116bb3ddeac4fc27165d7d5387ea0eaa963ba3fcd28bbda753053607c9d76bb2977e7e15695a4e922f348522c3df49d789281bd70a39db9718aa259997a3a5c9c7bdd7fbde7078792ce4909ca2efb7ed0fcbaae72c48ae021c0952e5ef7e569a2e12df64974a2c0af1dccd4dd9cc1576e1f630cd8f8e60bd5566de711bc40eea8358c025984dafcde3838fd0348ac1d5d7f4513f20ac862ef322ac22c2e1d6d238631c5048522c1c5464ba55f9ff4c1dc8132ca7c3245d540374ed191ca00cc43bae8fc824e18d83e481374e43fb19c9eb861f9ccafb005c009525d5024c47100580d5ec7919ddb28972b0988b4b0b408a75537b424318c0e706ba8a4edb0a13730d6232fb1a5555ae54760cdde6e1344476774507e414690da8443fccea1c1ebd5c47a96fe2c1fcb69e7d377e359c43f2571256e7adb761483f3d814d96c1ae16b242e91bf78af86f8ec9485b5a1762ace803c64305c57d0897f4a059778a1e9d6cf18352bacfc47c57acbb1ae6e04e27e83c0fe3875f5e245f04e983db085a3710fca645533b87f8e3ecf3a1a01b8fb88fda78f4f20cbac99f71ce4c50a829112dd9a5c27f4191145a514fa8894467704cf58ce847d5212e5a0abc0c2a54c8ca4416c3b99fd5dde80fe85276f166e017ba7b73dbc33ca68d681694c93a495fe42a5c463c7f0f920aea1209a5cbfbe2d1ca7f5c2a00dd79e5c4f511031b5f4503565d5f3a7fa9be4fe244cab01e9a3f0d432a58a8ff902c7ec52d6d5956d57de83642e4cb86299406c408a69edefb75c73526cb5da5dc9c726caf4a67841e2ee89ee84b2", - "priv": "919f02200622095e1406b0d36b1a90a3702302ad0637553809b0a3b8fd3b1dcdd6098d72264e7d6d4d2526269ecd818bfad40d6e450f1caed968e46dd015bf860c64f11f1c8b68b0a93e3a587b4a7b668405275ba0e02f7a9b9ed5c2a3a07d58638b2f079d879e4a963a71e48aa6a1ad48a53fb6975be80a87eda3dc2c45e3e2535347252511162373444883864234312171761112443113274541262551337205657337562142564641810327758354632066283246026032660562804546204201032100470857008704485318757233871080537100440075887712430860310035716105637805207148726226407183117674134077685281072455240143304525435254517217271628230002881303005708644321451536774560055002568231011653601844825336871747306308225147337254564776486761652475071243277768387525351423682277653676710247471164822022210263745461742764530838303826607831325346722787012407686084857676626567311027633317684127048724810304183188573153261558525367337033801513347178210115184560288328727438522687047476323872420601657314862574234236007814048147752447545347484058034681872780107524724278612143027328675538021258766156243708623415106424264857207356713470438274025516222771841842254336038556352053512561056210538731218660581146781731417410102603685057454531087820334516527768741004147848406586028810822338421580355365452504827026415403608881208676827215416335512862313241750784333244556575172312606561322356524231667412531172858170544156587437378562074674811724802217158383553162701447171412448374380216533350052350232168585430430038546666427434215210776566432862887475236726102445460355684288760664335323010118554183206073738163224141810160528738375535763352866840268340018558752747872223772826467564754525856800736608302314355680585125466035281342871425278510600680607610868737872577318456358351064687712720078162564728847764466144165122526208337786674382106466856735504105256432573426072255878810568204077874201326268870137766250031860247320056725710627478252872153077206662734770617680505174037136271378240535272306826168630171048300027443113217376461110152053250267224762485262338638447582146463383730585507550657233653638216033427160072055538301436882311630532018878501457673434108006610310811853163472486135380248156020871742778818010634356287622737627032567085008145130063600135307373066250323073525614304006334526265375820448468046114113141828615350121800562146785177371376766480605223276434131846634530460107814758043353551835534481112537700631102252224444448644311222281052385284857636008820160843864850064545034076558382755214271046680842130583103778217641677217787005862414285106751001024270630427040075517615787225164836210742813206221343126760806276705656662837772503318234073411728338565231372213525857540671013027723486135138826824336244204230151581264235632588644223333771521856662577177028188663150465003874131033684300235477368611231125344672380206712007222430300558053788063326274337621554730280578778138875722058258442357632740701132645843862338815650446440677274306103004233323287706324404276838811203068132048447336288350384168670840521354057564146760626677354826831558367781860451050315725567188201475818213440704580241507306186380161351432371542176271552136705726572162781943a096adf0af810187f7ffbe7e1889300aa1174f9e6d0a86989c07d14beba934b88a1c1bf040a0f417bfc476ab1f88f58608609de882e23eaa30b70720422bb19f8fa49f47aab5ffaebc8943ff6d379f0fe8b6f8d3501621a2c550bccab4dfda85773097690aa34b1d5629cc72baf11dafc173b3ef79bf07e7f227876bee79911241664d127c56b89e0cf0f0ce2682616ba0e0712fb4bd025c744812cb0efcca37bd57b0ca6e732b2e507921f6b763f398e0418aed1257a75da7bba0bc52d3179cc3d35079702dc9e4a96a384d7d6c0056f0eb8b0c5974edd43ea0acfbe53c5f7198c4f7ddb2b5d07544baaed6e8dc14fd14cd723b4e90ee80649eddb402375df04111bdacc8ba98775e2806773b311bc4d104801590c17aa20046cdd6f28a44536e6174eed2d0ad4041b5617aa9395712031f1227646afeabe17c43eec78154ef0d5e890ec372cf314079e80c6c680529422c82e4e74c8bb35be3ad04c4ff6045067e3c2e4fc1055e68c8ba0fc55f21de15f50e46ee5a455865b48a41b44205a01ed6509994bd7fc9a0237323ee302acea0152355bd7eba6350fe80314c9b6d30feb4b5af6ac0df133733c5345a5b2eb5db77a401f4135ec523f95f13d109b42c4fc3b8c824bd0d11be7a6b5a74b70e24605914e4ae44fbff0f14ac56e75a8347dfced9b1cc22e2f6cfc1a72f444653af7abd1170774de8bca0f7d8b80390cb8aca45ef671cc467a674b3c1b212f41f029e492faeed1749af0e57f3f513da2a43ddd5a39de2396c3ee779507a3e7c99bb1b101260b60354553c8142225ac393f633e1880ef686d3de4ab903babcaaa27109949be89045d4fe4341ef15b833fb0c1df7b49bdc3c949687305952b4ba446059d168c4218da3748d88713a49a14467d38c668987b461ead58934b0fb8ed1b92019e10e511a1a2b302a880570df72b3903780b281c17dfba7b9d1448a81219a5212e228b58b9ee6b73a28aba81006ab7c31bcc56d3e7c9c5e8f1e1fe1d62fb61e1b26121456a909b9516d01230f4b841189fbe50df83937057f038e4cbe75d347ef024cdbe00bd73f9680a36b7bb26640c49570f6db11aa917145d14c56091d0585fd6d42db68b8bb5ebca9b555364737c8ad68dd72be29608324e651766b1a6936f8c8b42d902ed712e3edc6f6b5e5a07d4c2b65033958c4102a0b5a6251c27e2cb6db3a0f246e0d7ae6ef8bc1027e91b705a674f9690a73cc2d5396726c977e15dae96859a01f1cf0133138f043403cbbfdf079fee2c0e345c598258bb03bc9d77db0c5743d56f702d9031fb3254bef6a141fc529f09f1ffce797a5d343faab8854db3b88ea42dfd2af8f463cbd6f7733a221c528634ff3bceac7dada963fe6bfc671527ae0d117acf1127580b55e5c4b9fd980528242341283d20bfc220fb3f89b5710aacc60f9353fd31ffcdcfca6f5b1cc594e9f8fd0f3e9349ceae2b25955a7b5eff5606d0e54aba830b29bb257ad63c94962f167f32c174b3ff9bcd0db1b97ed070a3c81519f65da57e526ded042488c0ddc4b4746754564a0022592da6f25023f086bea4a9abf5023bbd53f193c949a455f1ea061a8da38d93fcf0a41781e46e91ceeb1287a7a9cfbceb62c38792fbb967268365e9d6469fc18fe2d2e0ca4c5da62a0fe4b8e58a7ad31f2617e5377ea66768ac3af8aa6973f36747320ceddd50b687b314e4345105248f2b9b1b9451c909b7197556225a56030833fea15f1b9a088450d8ddfdbbf073481f50795f5cb9ca2b8e1ba02a02657718d823eb37499824cb0830fc6368ad6793ea27d171e7f1351aa04d86652e738140b707b17c7548f9800ef75b2640da5dddb88d34e9ab788239f37e6e4d5f7bdeda86a1a35514c022c24107248d15c2b07e1cfcc7c2f239be83c585f7485df3d893e99a7d6a8a6c4e58f5f8d049571bd45506c6b64b02bcd3f778a652dbd5745cdf4415c524e29be7e00ad3af934366c3e90b7c7e987f6df87498525206027ab905ed56cac425c3f89f676b1cdd1e1e44eca7e0e2868b58a81ed88af0673de18e22c2c58b4540d03a51d5740a5ac058db3bd115a45ad77eb66aad1afd01bdf61e7a81946f0b52ae30acf0ff545a4574f6b8383c041bcdf1b358c2e40af9a98b31996d5eb214f047355c59ddf6cdc74e1ecc931ba3814e2854aec822ef6b9f7b22fba347e340a629cf0e49ad22513bb390f88beb7993f240d8a0b6dab823ed3f13a05b392b22712b20332e876d14c51fd09f2158833f9a7dc653605cf7e77af15bac2d1fe6455ddc105ab28fec90b142297984f0398d5d5c6678977850a87ca0977b94d0e8dd2fe094ec00ca615a13e7ca73ee2632ef460bc06f3480e214263f8c3d22ac12153bf2d5670c87df4548521f1ff527cbf044c01156b3fed897059d5ec24659f50210ba483d0828ce8e4bbf64e06739b04ae712e89439ee16ef5056082c45dcdcfdf008a4cb806749036a05209101facd435e456a0339862485335b7c0ad0ee13312e18ec8e9feeea48b8c2f1bc07ff9911255c0b1a9836df57b14a8ae166b3624cbc71c4b9f5ba0652c4029ce365aa6ea990b032957b26d02932c2325a3a956051d5bcef413b0de3fb94e89797855270d27a2381ba1039942f59a2675e4e645b672fec30ab3b73f2495c27a47ee3ebc400abb1cb54ff15f934fe8b791fe3f3a228424222b88d8e676f8158a5f39034417249ef1cf70cb94b7fccac8303dc229e6187b2e1b0b04701d9dfbd4ada26f766ef6a89ad54906a608a973d5f72c189a2bab4993862fdd7b54e24e8e249e6f0336207b754396d1e508943da1329ba186a366376f653a0ca2d4092228e1d82b094f7d96cabb71673533f51ceca70263744d54e945fa027f2577343dcde29ed6b1820ac47bb5be66a9018a5ba9277598267390b5b63423c6c8d6211f037e841affb719b35275826b98dc9a06eb64195376161aaf7e34e1767367f42e25457cf6843a6d5263f62124a7c76b8898a90578fa477883776e799b822d5f595f2f7169b76fa211c48b7a8169ad4c7ebca7d967a7b48e77db51d3faa346753970d50e5df88a65ad8e319666a553a68f4cb529be3585400211bbc4496dbe5b0bc75a7c5079fbb3dbb6946d911361d69679af4bcfc8296928a4d5fe3fe21bf0d0ee246259331bc7c1558fbcfd53741b4680d80aa34f67e1011bcd4b27a7b9c6fa6a90fbd916eecaaa000ab00fff4a933273eebbc587aef3c7b2e172ef16087f6adef740fd12c30ff23d2e78d9fd36c74739c86ab3f1258c8c04d66dc611092eb653a7661b28b2785aa6a9a9eeed2e33d857926de535ff13a6a8750e6013afec7a25cb85d35cfe4c39b79e767cb6a0406ed3db06b5942b9bf364e1a1bb13e69deb759a0d0fb49830886d5dfaf405741c073fe3d6dd3afd4d4f8282b6c04c89abd1bab8a2e67e1ba0005861a5d06ab2bfc4b674a0985c4145075fa34a69036eb7c23333e986963590bddc8a849606a173ab3002dfeb4268d26391d55acb0fd16191ad78" - }, - { - "seed": "821acbfe29f941cd0f02d6bdc0112688b212d5c925ac08faacc248e7510cf88f", - "pub": "fd5109d8f14ab2d879b5147687b0f8b89ff635d61be11e0f7542ba19d611758b17b5a84b76c1b3e7ed0c4c857a0c27f3ddaba85382a3b84768185346edb47c3def01b18c78a91bf46b2d8be7ddbea67aa746ca879fd71baf265ae6f3a9c977c055c678365fc92bf8aa042d197a5f9bed4fcb58aea2b65fecdbdd93e2ab456510a65332e08233c0672e9213b7124820567264c5d12a5a996a595440ab364f4aed75b98a77838c8e4e98cb0f53bb9d44115bb69f02957725bc11050cfdf0930f82e45eac8f709fc805683cd81dab07a6b6fd3e44ea3251bb67d0edbc895cc9a3794d240815b8618ee49eaa29d7fbc6013dadbff2a48837b4084bd6e8a7d522058f5bdc77f378b3f76d483fb4c9d99856843c639b3ed99ae06537630e7adfcee1a7d3d9e44e4464f79f9acfe32c384744deed50057fe32028c9b2a7b84086ebe6545e619521dfcb6fc02b90f00ed8769497531aa39477c3af9dc8e2bf9c51fd329adedc1725f760ff5e28b5400d917ac413eda735b58b26fa7e0c6e07749b1a5d087325edc2f08ed9f9ed5a98e388af03b44860930904a907a66e00d09cbf98c0921248036f48323ec5a42166bcaf893195dbeaabe232af704bc64bfb10e43fab2874602d8641cc997fe3c074924b6cac536d6536c87ac0f8f658fc3f99dc98cbd835520bb3441b55ccf3ce7f263451ca1b3cbcf45d12c3b889728eb7e401c1c2458528daf2c40e90101a3b423a4e1b8609e74c60c9b7595ceb8f35fe51af78122d9c487bd89a03df414746d0f2009e852a3360aa422d035715e5713f7ce28d7d8db37c40bd86ef6cd55c0589b6e52cf9c7643abe4096ee53cd1c1ef65e1f9c7286452191adda05f133bfb18378b5d898201f7ef9fd77cf76a4a81b8a732b316ca1c2682bf25c4ff2f500f55fbd60ec6dcb48282984fca4054e8a3dbf5e0834b312b2c867ecd962f27846fbd1b5faad67fb4b17c20bfb0211d96039515f9b0ba6691e8493f122236f9f52325ad5b1e30c3301c0d3f60da86b77bd81b4823cb636acb3dd28052a278737d2e5b07b5e9363b2395b51f1210aa53f627f58109b695516e2a8cf756e5ff531dcc0c51f3fc5bb95b28b2ef1676f15c6827a4cb2520c719a90ba2ab409b31e74b99771cebf87aff0bfe549bbed6b678ed0b331c154d42fd7f6a7f07b99ab0460faf7803fcfe336cad1d3fd5760025de4c2727d386306eed3b3d5d17d9851a5744ec70b3a0f29a76a180c46d2d49f50e9d8d1046f2bbeca53543a0c3646fd736e39175a2d66e142b0a94927f2a937846a1c44cf00f55cc9b9d62d4f25af4f87a25b8bc932259823f3cd59f3f09adafd033f1802293ee5cdd49e70d8dde9fda65c0ea4063d4f5f0810671635885b49c16601f531c7fabdde3a63611ded6ecf67d621f2cfd48488da31d0fd102001d44ab947ad5296635c45d853624baf09a5ba447cfb8c874ed98eac7b867ba6cc10a4675e6c2f5f54eedcd52d500da4e15c338b1e12cac96b0e52d483a17f9d1f90c4dd385cf00dc0ac12db97ea1ff33c3df6de8bcc81e70c6c153c2bcbfc6001a815d17ecc8c61c24de9933becc9c9f18a790564174bae2599f93e5bb1216fc2674fb34cf153ffa690962bee4e9080edd9b49e3eade139075aaf1a187531f51d05f7bad888c1e717bc4b368fcb12abafee6b29fe72132ed8173c4fe6f711405381d3e2049a627f4de50353ce804ce5eea3f3c94008156e7042bb252cfb13f512b1a5f28a10cc70686b22e9759c4c8a62e021f8366a4173a0d3bcdf8b550eeb9ee396bbe86d0a851b77b2b404658ab1a8b3d69dbaaf61cc7d539fa05193a6f70c2956b0d2b3757157f54aef2d70dbd8b0d48d70fad4d88b11465375b7cb6178f3da79268079df5110f668168c6e9bd362525edb99b80f87ffbad11e8d88935162251f7b4df2578de0532551fcc2aa0a23993c6bc289ac0215cf664fee314bb4c21354f8b69bc920fbf0b8bb2dc499d3e4bf583b9f2eb574a5ab25205fda5fe123b09a777b10e945f508a22bef885746b6f4ca38ce73d2b4e843a3cac214146c71925efd237e09707b138a252d6396d8e9188bb08acc33720c7dd7a87613e55c903c436bab24c9d5b74b7948eec3c44b337201643e4caf2feff9b6aa4a553d1a6678592c630d11d357348e14a8da3b6c274464f96ae6554ac76bd4340361e7a599207cb88b7517679cfba163aeda592ca982aa4e3e37db705ed5e26592cf91dc803c4bf9a8b6058ccd426ba80b4be2ffe8d0b2b5a9bbd1cf149f4ef6bcdab30f7a4a9fd2f6d0c2c9887ec40b41a33e4aa0fa37fb61e9a1736a78e75b0e5b668f648420fb37885bbdcbbcf7898b77159083ba58918f7f190a7ad04f6f941fd99a09338920e9522d9f41f9c8807ff02c0350d0a91ceb260cc8f4690b2e9d5a6fd3a4032aa09ab96a7b4c02b3afb62407546b0c584e142c93bf127405a17548ffaa23832887adee53b90117163d8d5ccaa96fab1fad4db883688d376b3d582363d9816cc85e16a5be1167f25883184fc078eab9a0c09a5172c0f557bc314686f961faaa93be14b8c239ad5925b2b9ce7c2d507141c4705671e7105190b54ac4008d8d845435a9f68164e7dead5893406dd21898e4f6ab7cc23eda1d768e427f2349f329fe8a838a03dd7ded95657d82d05f6753b6e3800c2ce345b1d33ac488534171fdd124360ed5eb4b62061d61b89d95ee2d3d9d5f8792fe679abd0addc5b1100a5d56ff8c8393f6698ca302", - "priv": "fd5109d8f14ab2d879b5147687b0f8b89ff635d61be11e0f7542ba19d611758b37f4413e6607d0819662237e4f7746006787833b1f0be10734308c1e564c8fed69592aabe7289459a5882becbea41861c798a02a0f36da0aa1d00bede17b87fde6de5db5083b879955b99177b83f46383e2e5048700863247f8b00dda1432f9475845411106010802403124423006207171123637626358064004744217668563237888426103620752544733884730188200687105834153425720865281708118271854426277451381137237063130331623234106723431860347548763207658577260187146861448155686826455003173682641840333567008330412485633328752625476441625800267213531873672382311441364125312140451047067036187188453426367824516587741606322451571174808077083645343475863427745255815618608637822668140778022078564357408860015574881153222705772820283282645138703666837082845457545642483327554486635104572840030702644546883155868854848727734687116530122331273316185560038723621705252685722207460533380311867184216400552714105740853578622762727822013200126021044283211375323117003650187002088603640345838844504335503120832113026778216041020078002871175114780338718740318457762655342324868368435104511507781314186715333714808404824660120450275541327480357767864878521734380425386623801541346774823118010158808603360723632020412452027121234068688716164441521887108240101786315371520841447607250516005315365686168717574678054651203116875838316668026521024171872707164174688353341467360173172577764432418112331306083318608605402151567381436862124117738672361158226325887710338805385437741854660070530741053300731051058032536663754782277723523405535684511367423724838044746436665367216702401504057760861543160842185113378015224425623321268204241475232123052525186526436170475223506404246556168704551444551388733525384672264531670007310781725425740047878568634613747664237017616081148818153324800302322626514831370370752655505652444514474570366145827603375858080460822137114012511117868251538483208262330710570084046510350650067607452046145226203135104263664202836618344162630317470784727848257402470148421118752145271066152161743850236604061501516023741745433718841304847033226752765102660665216844000747725857377655737286628628855470800115846468544603448604421136682275115820474718124475360816350707076840045427737648741006206344653466760485601222162728263052643450841137207405423267533600508015253620825076388520610231453565801282615681627051432685018612236467086817638250582501884472046848272635753014406331123268541531386173156646817565463500686735817646042771537270561435557563865543005755720030384235037845153625183357188765067524510541785723483746082513261716357675385520117254805854813722260257761547732624410547504153484802545113081035450188274886618452447827427357657813402550236060754048666817727427460350022175101303701227746503115654701150825304136500402467436180731888868347168086754418454456816581305381780810850606827744730528684184014655603763554220413703356318438650383817117084323856267162872086718276068621466341542271674584731366742432452022720723523885440383735736758540137861645710336031513401537787442784487630878114247615133473366832843613332177588724308575184307203156767071bd4d1a723fecdfde655ff7613698836154d8f6c5b46e3cc037a90876bafec493d244cb2b771bce1bc5aaf7d9f8a75d94a2e9c6746daa9058ed347d992a707c5d654d696521403d04bfc933ddd819c17a97bb4685a827f2fa843acb0de979bd88ff69ce5e62bc74bb3b0917eef8c603269990cdc67e4ac99a6645412a1c2326fc2d13cb588740f71e9012ac9a07ef086670bd981722f8a7103cb68c33933f6132e78803316c85f6ab3aa8bbef2a33a19000031cbd73c643e226c156e5cea88bd3743b3b0fe16452fd7bc84380caa4defd3ac5d38db01f74b9aec1e3c368a77b9fc8df87a1c909a7e10b9369df94460b8567c38b75267ebe99cb7e07ee626772bf70e721b00050d350baa16b0ae07faaae61716fae72b10922673534e83950769a5aaafd95d3dbe428e66c7148508d2ca2914ab6dc20f0bf7ae92ff51577093aa98fd383a5e62791af20206690bb1231736cd5449ace93061e2a71fcfb4ce9752188a4a86302c6799b882e44545fe4667023fdef2c13939b373e2a85030d23de62fc85f3ab765699e898d3f06794193695bb0495684a4afaa4c9d63843ced531bc122ebbc3d9983319968fe57d037699c3722545d5aa32fc648cce93ec746c020607513559820fd9f4178feae2620ba278613a0832a3068bb65a445ed00d0623dc6b668983a5fced6d8bda41164e8acca99de3ccff3c4a6d5cbd019f53f6b70c97fdced46ecb1d6d969b16191da7fb093a0200ab28055a045aa9b544a543c96af75ef9950e36b9d661999929dcbc2d697cfc6a3540b56ea3e4f4187b8d892447b63d80b75035d8e594bc8d7d8fb55694dade5463804985b3718fcb59a946bb3b66d6bb38257d0430e18605399c6f460cd33fd9e4353ce5f7dabab57eaf388310b828bb008f1f8850626680d2bdf2d1d7fe348b18ccdcb1430a689954cfd60a683438000c1295711f7196f9cd524243813388702248346794de6aa4ceae1cae5e1ae474f4cca0ce754b8021464522e4a845c1fad51f775ef7375db6a21004ddfc8fbce0db93dc275494e937424c4c3ee97063650930794917f57bfda70d2ca74b1ba7235ba947c587b1c9d86ac4cb9c8ddbef333dc988894fcb2615b3562fe939a5d171257726b6c789adba53dde401d5168418fa6c1cbb65da20308df78ef6a719c059ef43a5e01cf6b2ee5259eac541cba7b6321e5b592acc42f6e5278785aaca977e2658145258eafe96a544a648e709b48ee39646f1b1f1040cac64aba7b6a69de4866832fa041c36252843f20fb4679744d6dbc09c8260a3cec898ed2d8c33cc790d2d7798824f0a05a1299c4d7f2a4ebe7496956a5c7a033340de8a044619d48013be1e4b43213b3689c2267d4541853314e807ea6a1c69485cf57b80a106246f10242e3c96093c960ec0f9c0159a45b9007b7a8141a1834b8b328f44ba0a1fcff7208b476988686be639362cb120465d1aa9a6054f596270e5a3088329a91a070a6a9b8d86489da8ab6fd21f21b163d0dbe579c2dd5f102dfe9fdcbd9eea6eb32a236360ec67cc685495df8ecd4e0da5ad27e9f313e3123828a3a7f54d793b1227214759a72aeb0d64fd2e9a134baf89ade482ed7cc5db0c9593c63219cf38caadee0c0d297c9201f7f25680f0edeaf516a4914b2a4606234528fdb99e5f5c0cd2a881cc1b670ebd170360877e7fa4d884a67ec0e3d6a4d3cdd304c4633a1e6de168af86fe586895ea49e390c0a9a92662ead24e05efc92c048372efbd3af11b87809c0d7efa38c24c7e082db4b542468efca41f88cc7c999ffe3c6568586c39f3750745f0d3f551620c227109df9155437a87a04e08a4feaa648e9288299e47c351e34aa509eb4f772c78e33ed4e36858e4055e7e3af5a958e96e69e93bd86dfe5da8d1a3aaf0769dd87558024f2b26c6c6c42224760d12b52832326b7a1f70ccd530b9951cb3b7a499c35043789e79ec68cd8ee1fd56ca5f22a5d54fab7f0689f1b9584fab8aab9842a3a30c8780132f14aab121cb09f0b4941a882fa8bf4935bcc7f2f698d93fe10f2393fa96b9f957296b24669dde4b600927bf5a469c0001f0b1d8f1df0e6b208eaf552d52f15fd1a80b1b4831e65057641ff84e9cb6811980dd38c4b26b11265b4e71cc306ded99e3d48209545ddea12328a1a99972ae9c849718a2e1d4e356ba7e93409f9ba01bfeb6ae78da17df50924e428926a844580dbadb3439d98c6b89818907ebd7b7eb11dce48478cabe0a49dbe5918bc45db4b88fc045d1985b918789f9ecc59db72f2256382841ad1317805dc32e60ce2096562beef9482edb130fed0b00335af2a8ec79380349e1564c3a382418550623e7a87a7caac056ea6b44fbfee65c93890fa3aeccdcddd24469d418feabc03543bee545f9fd977d77fd44352553d32a365aab23e0916f18775e3dc4d41163794884596aae4251f7527725c98483c72786d46eb2a11992b40dd0c69ac7092067b3eb63a179a5c61446fbdca3b21bb919032b97962b7e218c2dc34409ebbd5bb360f2b212669cd16f45f5af4efa777627da59b6e2aa0eebcf2df02d1954b16bc0b5a718bb95c1a905400c5e0ec0f326c8acab20ddb69525febcdd32067cc74daef2e79511f10cabebb69f11ab14612b38190f8c02c4526ed189793d059ce759d56b00505774aaea728c79cd8d2588919500efdcb2cf7f870c999ee2b5ca16cad7cd92c50da46274a1946a0d8b3ef4fb6d498339f2c7793267c92b0aa4a73cf40c362416b487a83a9caf3f7c6772ad70ddcc5a9d1fff56b5e37b821fc398dcb15e60e1fc0d8e6dd569e315c5b12187ff345d749d66967f3e7ec97117330894138da444597df7b5f7a014431c253c8d19f9e8e6d143f406b6e9518f18eb3e3a3b72cef48f2aa245cfbc1f1219b4508bca6efe40f80357a1cf1c9d061955a746318a75969ea691c83b5219a9354e0fd92ed1302314944bf62eb3e75ec9640e2cd6e0a7c955efcf41dc0f90d25c855fc9f54ecdc4cdb40aa95e7e53f8dd2dd6cc33f2703e8dc4c09c6781df792e6dd945fe0ea4fa760fe35380236138f6b49c99dd5d6fded1151d5c461daf39717916cde27834bab0a5e3d5c0c5fdcdaffc3e372f5335df494288d5176786ca73dbb2b58fd519b10531a2c9d6d390f7d4ef4d9c4f8d0c6f36b68e3b502e2d0f4c97d027cf8629e2239b3ecca9547ea8d9e8a357602319ce01b0b76d2f5cc5b4a3a906762554a37f0b8fe5b4df29d434d98822c9d3ca495a103d1096dd042d6bad442be6d7a5882ac7b79c9b588f10cea4eda495addf22a8a52f49d21ecfe6fedc77a459368c18819bcb9380a0c115a5280cfea7136ea7359a78392c27049a55fff75fd69f70d08e2fdae617ddf1e43749d9bd0dce026fc0b8722db70ad47fb3adf73c1bdac24a27a596739f7ab09b92a6005226ff18abd52aa5131bc9f86c786d87576bd3d8291a471d4f40ef51b214069d7b0096744bd9856c499641140efea44192f40ed4cbdf2c562e30881532543471258282" - }, - { - "seed": "19b20aec7aed1c129b55d7a5143192a3cf43bb55069017d695581b74006788c5", - "pub": "c1876c7591d9fe2918af831763b053d7ced29634caf7c28e44ca8ddfe79b741612fd62c3049c2b665ee8ef14d040867275020733f0e2673a1aff38f32c07c4f0792a7ba4777256077fdc933f991adae12d5c0c79299769dc28f2445ff043d563dcbcdb9e8f3b238c441cc329e13925a779f9a3b65552ea2793f99a95577745bd8cf86dad4373b22a7fdcdc1ba31543c649c4b6b7c8e60795aaa4c4a9627d97b5c8a04be0eecab50e02f59139751dee11a401fd23f3a0b47837ea00cc146d668992dd97afef17751a01449b0850e3ab1838a512015737199483769e060cff8b66793cce1fb3e4ea781c6d09d12231775ad1d98caa9b1eafb9390d67d76ea3026113396b8dd311516577adb15a77cf47c2082b7982b07687c2c88a6bda5f9e5fd7f2af932d947da6fd42a219e297e65486b5187330e4c465dda55ddbcd1823d7349d9305691c3edca07dd547e46af919c780bb03c670359ebe80cd4fc98ddaf6449677fa7c045cbed1c04be230690177ac880286407e301219d305dbb3fbeb56b0ae253af69eceb2fb19fb66302c828d375328ce26b8ef9fb97bc95b35d9f0294e157a98f50af78a451ac533529e98196987d2d0e63c6f9857750ab8ce1503814c87fdaa84b0d345c477bd8e87a09dbb0c176573b5369a083c852ef8b49d4f30e6082e619cd0e10a141b161832e94b14d6b0150cf32a8054dfec80c2500f230d4fcf86236d72c02edba3cdfd83b28eb7a282d4ccdfa1e1e5438f54d15704e76c92352ff2f28bb112372e5b532aee918dcef2585e3163520a08182cdfe1a3d35f8f4039105ad2bd4400c6f8ebfbca9fe312f7d95019912e2945890ab754881ad378ad92d00498eeb82113897d555dfb6ea7a49b8d7115dae705c2c7be0d5bd7c79a19636884686b9173ac7ec14310d08361be6acfc6fda240a73722b6704cc3d2bc0f0c0c040e44d11e185a21ff149f8af17d2e056a3c3b5a06fffb6e8bd3650e538af954024c4e0b55b23941ff945513a64453a0ba9a4d3df118c31263a06a3dfa7e258862fb8bd066179117f878662746872c7ab66f2264e4765ebb0dd19cb31f55163d8bd964d3b359a0a79d4695d4e0a1d6106cff71aca80fa61841be0783d3cbdf843c65ef755a7891c0c40c98e6dad9f565e51ffcdd4e982173903abfe03ba08bf60e5f14d3c88e00a2d882253d88ce6860eea90a9e4c2aa2edc6ab0424493c1a79b5b6a3f73089f4a64d0b2e55b7ba0415a53960b870bba5799323dd2d00199e2fcba9547a9c2b823f753408ff143bddb72b3c1e6696eb3c6c3ca2984453b1916ff4dfd6b3b43477c42cbf433c752d0749fa7d13e53363e6a22d085ebb93aaf260d610ea9694ac2df8bd0e7dd543fef57685e381630ee414ffd89269ce6f0d9d1b1e32eb744120325f092596ddf8cccd53fca530440ee9000edc1d9708d0359a2b8c20008639f164a7deef0e1f83fae0c6d06ab8a4e82ca74ed9ab0144a93f681bbb54356567e24d8f8a8c013d1e879f666ec62b94f2617c85cd57323a72ff71ab92e322c339aae371ae06bb79aaa775c3e52b9480619d6d32335c8bb45ebfd11f8a5c5ca339b69e0f3fced6a857ef3435732919568f1212dd9d02ce7f3fc1b22adeeb3be460d19235dd54c85ad0db8165f30aa209f34d043a9d9dd186003eb29ba7dff1ecafedd36767a7a389c685c4d3ada09626c652c7985f237d69c31db93a8cc116bbae071dfaf8466908a9975c29d8cddc236ba5eb447ef045ad83ccfc8ff9663d027a8138c6133a20d9af2f89b2c183811b8a6868d5701c9466c54c78debf571a18db524a7ae18c935b624446a8b94f25060d695949d7ac47de11475c427b3bc987cff890932e8bd341e51d0dd8b178d5c4f40c35b9b2e2f2ae493029c6c63867efe1d7cb4b02c53c5646a9eeae87e6fde7c073bcc7f0a79b4f7e25383185292d735f0de85b4f3fe9fbfdd21268ccb903640cc081e19bee7184d3c2338c83e2259e59d8606357f325d5867265a2de3fc8bd88ad8eb2d4aea4e89cd08283dbf1e7c5a7e97e3ab43d9a385f162ce3ab3ccac6f86af9c45fcf60d997c3a6dcf610dd4c6978a3bd071be03c0495db413d5d2ecdfcab95865f0cf0c732aaa3ed403dd9901b1dbfb603fe933f994f6c0b5a7fa6788af95f676f20afa37d7590c31d10ae2b0fa71239499737c004e7436b1539ecd7e442afc74ee027398ae51d87128bedc2c2f1e8da5fc017a748d6d51428853b71b4f8d07a593ab61fda4c401cef4ad4a202e957dc207b20e15f5923cabd23e5fdfb19c66ebb92e1a8226f546a3637cf69054cd173614e5b69462bbd53fe82386bbd5af6b807db21b6fec62ac9b6fe7f6d1bd777b2940b43516cdbfbae26722f6a88552544c656cac0c1726a3e5ee30bfc1e140d40ebf234bfbf07ae5b3fad3acee3f8a134cac9b9ec925e8763f21e85a113c6e59f5cca70eeddc2540bed7c92817b22d464cf0b13cb824684728e1fd84e497e4d8b1968f9103e5b820d97bdce02bbe71ce0d6a8c26769abfe48ed47bfad693eb992632b6b934b54ec903a5c35cd8845f0e43a0e856bb8ecd9ceb4eb70010bef602c7ec170bddeb6a1ce2474e3323eb133be60e1a23c0aa0a88dafdb69b4c492981a53ee45f006f687951f13e6399c0d3953f134b5015a62817f8f631f22f029ee3167d9cbdf890cc68818fd12dffe4be01b4bb04325c36770e85aceab462a919b5a2cbe9f6198f9e3c8d8f253818c5c1b6b3472df05c8", - "priv": "c1876c7591d9fe2918af831763b053d7ced29634caf7c28e44ca8ddfe79b74160d9539d135c3137993c93cb7e9db32d97bed2f47cd513927beaea3ea4de8db3bb6f69efbe8bc30b741160501f042738be204496408e7b322b4f8810ce5f0a1b4f5853bd042bdc71bd3f713995f90d2997be98853a3e0b05eca0c2cd529c62d1d31142720430162555220261408757487051805486321463505328548138872674635348656038584807581556616567024781108748714006466586518105002840004152155071684402283301625468608582682871478285880112418701887856542813261486851086715532015038018055506582001004343174024123728627110402632383478155035530668058030807805254735026344715438314074570828778555510310503127760081644038768664440013167025735144760220153688771326556654136677416836236681275767825505783518026507108541306761822164356817775213250763580875702357583307542021077861788684686144273011537008501712324033761721553654884040484566604226000214651473588064077132555143158421687651533365271426802716634284747711533266322568582853708027003861221727624188548224553846320154218535004558846614210714725845776845035032840301165860462661558567062356487726862640113066862340546354378052445185333237853473826544553735144445868050241350888774173617075453531720267316818175415433376853422836031112605825812128668124221221813720163332878132662740616835058334581511783268088514555323113603245767313468456805542257754161745144715584644762635222801770257403571224173224101775575421637641653561651523472523353220007246647685422882100323788035807815471744883353670332227331383575023847310756871261578822337587022523242818335102643211010036128440207207414604308060212184302087706651107415366331635141330688886357276684550512668846326170485080755401433066163136305042535141770172143571578534537566273505072131666672802302137400258356111170004050122176802185713363384107338013714068046336638073677671825887712654440634342104756450234366074785063373770138355536602834482336117841811656443744500552574381774725612554820152456181136173480528377444617573837506101566008482616254362626412148541878576272451278865273175261065121480628166312811217332443874218160274773587204140232054516151580731416010517360222140016312345165580552765116138228663835802871501003418662168472077781187768025576001388352286135461575165005568123188068230433318746647171256317558746767878042633203465265747801218226257524465703521066601441767437260017503655584555626781625645828607216813374401208635875826640523026864485803177516421032408802243351517420170357837500517573422583060107563784043772507424567258253886871303426754383234648741138366371401462647365832748247554435886122467742424232347324855363843371303526333082723501448384560734138412613126277377455378767072466561765062756763081555387882428742444264545182347872215788716415115613725675021506301847681043752187440344541180617014583366082216418784124548587567538635417676816656583151701337688684365852214350536148165082118684731162728603020045865388212864485217252720226467655245757761056558883368818036647577235233732437782724674158151572615477036118545377305340788610187136740007740123076210307123022813564872374047362802876653816510510783134134880883380826444c8103aad8657aa9b63770dc7a193dbfa1e0118e192420247b0444a7f836ca9cdc3a0980662ebfd520d15d923c37abc4c3fc417ae01f017b157b85ca4ac48b3a5fbf10bd5e1f3bd2ce7e7477f4d47cb502da2bf1d75fc48cba9cc78781e33a3076a96f7d482609820fb1a1ea91ea2c423da8c5e9ecc59f34bb5d58ca360dfcb4e4a10acb046ac8a0c2f093fef48dab309a7645ee2ff18d88cb14737400c44b2efd12d8c03579a5e0fe1b260f691b9a9d001fae92d5c04a46d0232751d51b4945b86609ab60d80a9b04f573318062929cdb4ea895013b78d88b6379c1fba2e729c7be337dddc9ed90fdb05595d48e12cc38732e00fb97735476d423ebfcd8b91d7d17d9c9f23fc65edae2281bc482efac37b48b23b9d1fbe8b8aec1533844536f1b61bc8ad5c0db80df89b3db99ebaf8014a8050f721123b45a913dd533c8c9a5789f2d6bebd95cba04555e36779c2f1d0f562e5c8597970c009a815fba3f86d76ba778365365bb5d897b67076c9b826ea46578de54285a6dc36bd9eb85f0b282376cac0ec1ed7e22b05cf123792ccd02eba13bc9079c62528075652685b70e291a659b578cff8ec7858cbf990929a639f20455f3cf14a6e9fc8dafadc9415b3b20c8b26b5775f66dd90851653b30c382d3fcbf8c823eb5f6fcf70c0357f71ebc54bde2055615a1a1cfdf3a92888c5831a3ad66b5cb128397210804c3ded05cbebc4b9f982cd5ac73154eb629e8eaea4f5239e7a4f6a4628469169ffb74fdd8cd475f395e95c8f6cc451e46afc3977bbe7ee3d2acfc1c29c197752863c0ecd61060c90f3837a276da89a7496435923c2b89786724fae94eb1f585e8ea4cd6b0b8127b241a889ba2fd60cb8ae279f77ba7eabec33edb596d6eddedf252800f448c2fe0deb52c00b2c59dfecdf7761adae9ff8b7908a5b441a70b451e136473faa2310c59733200d238c75aa10ffbf9189580c53ea961a72fcd49ef3f7a7834fb0e0fb5101f0dc77819319223d1be54ce05321d70beb5347227eb13c2ef4bcb75dae62b80bbc3f89fb40d83a0ba7db94afc86c469ef7eaf8843c508c465d90f850f85203a978134c4240479ea0e241f805161e7c0b28b2e960eb281270a26fd00b0fcc8942125b0e73474b186bbf1b2a22ba5ca4ee34bdabc5cc9729b25f02aeb9bc4fb18f11053de96bbe76611b1aa5d3c8d1e256481be19b03cd3fdfc9be306f35adf8b229ca3e2470d65ddc3f3774c453ac9f049d4e81ac955283b8c85b5f52f13a5b9ae74b08bbeeeb7ff9c7db6f0dc10a8e18b5de83725fa5b1a6e5a009753c694078cb88e8a2e95dba4c5aef8c041b8aadb984f533cea6b560807ca8fac3e16000de18c94d0346bb6b6e01a739685207badc4c641201c159bb256e56216cca2dd471f34e97891785cf7e6bedd14c92fe0160ef1b25da80ff86739568f006e778aeac09ebf4fb56d2dc914d549fc91cae30c1f044af84f2f814c3bd9eea0fd43e04fb7c5adaeee456414ded08a0270b1c418aa964c31c0d9326618db93bb2885a7f734db1cfbd903d5a2aca03185b3406e015de23aef3df47f4394c6c406d63ede57efd3d00555592ff3454608e00d5b04b276d8d52e8533fa59d8df4da27aeb1a4d6e54ff340c9ab6f79df17057517b7e50cac46e99c2433a3f14ccf5a398ad94c433826d0497de022529c0731fc5d567a2b63cb8473b1dd8eb40ee86143562e6a549cb58a94fbec6e75e71ecdb0321d4e5fd2cfb9e8be3e7b6a9cfb42fc42cf3d8a8fff70e2e31a9d4df35d6aa73aaf44a0e9fa0c49f1ad3a624b88dbbb2ce5754850914fe76938d2fa56298e56dbf447bc1da818b2cbe6dba78a240a070fc43a9c776562864a6846a4929c94b4f1138abcd75da0945c9ae6f1ea9468249dff202f2e338b9be3ce4ca099315346ada893a49b969d26ecb3a05913da9ffc13327ceb3df6f0d1cd855282cb64cfbd0f695eca2d4c24ab18fe07a79f2a129cfcdcef608835ad2f56001e7b73db415a132eb72d0e752e08849cf5f663a841d25792e3073a4a2634d9b41c3f9c73464f4694d116ec073c67c507c05ff3ef5ff1441d2396fc4583c8709c89e2ec6cb688b3713934e76b95e8c10cd2f3b9d0f298d2b66380c547d992894da2554ce583743490a6792ff5490ca64868dfcd95c4d3ae21130df4b00fc50cea9aaa2277b76ce9f7cbf8778c30591a81f2fdb4f16c614fad89600135b8084bc2494a119470c6d622b4b6dd534d086074874202f9772c190c301987a0badd318c2152697e8397d4eef55547c672f35985e3f298881be917043c8b3e9679aef3a65ea7e641f3805acdb18e716493b597dadc3021293c234b5f3b548e82250fa5a2872357d961486cb95081829bb567aa3b352b64c0fb4f7072055fd8aae50f855c9ae69a1850beef309a41d1b91a5e181e5020fc73dd5a90ae7271186f470e20d2093f44e128e044e5f7b516d746818b18a8d4e155b0cc322dec548324b0241f4038c29e6cba77c80228ac9291d1e5046f7aa321548aecd85847eab71996e3aaf47738d06010dd373dc12fe362b599ec7b060120af6435301b6324b7b99771300c7dfd369f7983d1054c1c45d37c8063c73765cc399cdf2c7accff7a3b6f80c0110748bca149db1c7503e47cfba8c4d44a9466d1dc0f3758932bb4f960ad5a67ca4efe34f5d946220beb96c787d88f87587d3c09dc4f6de6cf1a91e463bd48398aecd75abfddb9da29839d78260db74fcd26d6918600c74c4218096d1bcf7054d7db853379b88235ac069eeba3be170d9d5742e085b468d3acb79fba3972e46ad34cf645a979d3ab0e93e1b69f16b4c1225c048f5e5cb06ae5e9d84c59ddd9afa1ba1291f3e02cb46dee9b22ee622393e58ad1cd6ec3a9ef39bc5cb2252c17efee60f2a139eb84bd7e9131d70cdf35983d81252927fcd3ceaa9a6256cdbd0bb4a310945e7a6ebe10ee50ae002b281797313e621013d1f9e9537a51a9c32d89fd4c830d47e6f87f84b9c600861fb7191a73ebf28f9ccb83d031ccafab2ebaf1f4b67b651128cf35f70f8315d03e9ac420b730c7c7eb1c16623b89b89015e59a57ee9e4aa835436725459ab6ec1c3509384e1e44c50b86251efa538c3050032dc9bed5245cf7708dc6c07382ca7b5664ece3aa5c357492a1cfb76d49d4caa23d237bdf1ea3f8ef35d2c893bc45329027ae33d9f63e9845ba7de22dfe6a7222d1329060c4c8181d92c6b399e71aba66ffbd4c29ced409b8e083012abf3a8a1a9cd64f97e972cafa4ca3861f5f73d891155f7dc9b49fdfcea857981590e424752f9d80bacb50ce48ac3b8c8f25062dd793ad88b89e94a93a4a38753dcd1ee3fcae78d680638c0b181a99f08eba730bc90805e56c9c89bbcd093e1c8d9737fcfa8b1958d1c5e022072a04cebf6cd3552cb1805a598ee9ff199144a5c4cee2dfc1d318965ddeefe9d2668281263143d9c38f4681a72096cd7da420305ed6d5ac10b021d8cefa981b0015099f5e5725b8d735455ec2ff2b8adaf" - }, - { - "seed": "12fb6df663126191038f413001776e0791e024b1129db3084a1cdb809404b555", - "pub": "8db98d451a84d7c9fdb7e2bd7628ec0efe6ba51499ba12bf981ef380195e1d8bb3e4b6e7ac1320c295dd121ae504385663cdee9bbdc461d9af9b74a36f30e52598e024fdc912f1d51924e3ba090d5e131218f69a80c44d920aa8b3569b36505f4d50f161a5deb45e736cf04e61d6ac17948f496bdfce3e9968861d267ce87d3233d12e0fc6a4db86895f7d1f436483ac051def1e5a4738342b95890c90176fb8ef27029026e333e944a88d08dee0340580a08dcc4a6ecab4761279d76ca4ded5aa147d656daa41ede66f4c838f0a04e2a7b8e18e4413becf01ce5415a17b6f39a5b7996a84d4158cb664ac36eb09980fddd8323b2207384f60a63baa446c0ca5a8982edf24dd4ded8f07181000a22f9fed786fd3252749dfe193301414174ca01bdfd362d25985a6cbdb315026f813e3220fe8dc1e35efe3f07772ba54861933b9ca9f8f68bcece60f9f28148395c1605890d5f2b3e859eb7eaa3cdc66c58c9782ab8d67ba6ec271f454dd8ef82854d2ce61b5a513ab8fae77a081d4a5b34cce0100d31daaed0852b9e77c904eed16aea439b46bb2bcf42fd3addf320b4f1ca1737b8d7d3f7496c7c77107f2bff1c907bb145cc2fc7f92cc3a3a4289cfd836aa2b7490393563e2848f0783ee4814beb9f1fe75b5371bc9944029ff463361f65eb6654b588f9816fae2083a4614de3af064d65a1254b4252c8b02f1919cfa11f7e523f51c99ef17cefb5eb1f692fcda240c3a0c504f2527a477a41bb2894ae3f3117e96fe3880d3447e1110febee17ce73f1ba7956f397023e6ce4cfd8d3e1e84868c94c0737ed138fd7ef28a7d6e0a047215a3490a031c2e7085ea975fb16d129b7a70521aa45e9300355b930916d40fab7e197244cafdab36c55caccdd9eb203f48cbab6da41a29d686aa198576ba05f4575145debc8322dfbce5a1d0899913dbe93f96033ddd73e8cfa20d92cc1e9869c217586e78fe30351eb421ccac154089eda5e4716e1bb022f264e76385af044fb2edd00d351b0fdc49b10ed29510fadec7d7bcb72edbe46650198c7b221335b354a7f6623842fae558380fb0efedeaa161d0ac5cedf64cd3fb1c709db76c8c046cb5337438a72f283476687d26987b2c6c205f9b39bc2db90ef13cd5440993f802bfc120f6062f8b62344231a268128b4aa66eb6a30ef98cb94cbd50667d9be107a04c54631570584fd0132ec1f3ae8f115c54ca0849c05258ce87e6343becc597087369594d1b847cde8ab9d7d3ee1911953fec22a2473064ae8bc3f406d81aed4c546c8e0dec5327f2cf883db613d5353837c823c005420e2114468b6b29b862fc6d0946964de31d2490a14d5022ed160288f1c1b08dc9852fa66fd00138fdfbf6a1297b90152580ab8eb3e7374b627f32233e513fc9329a5062b3b376c5a3bd11e82979a0310e6bab7a66e6a8cbf829e46c69ba03a9827ee64e0077da863e7b046ee8521020166108efe63d089a598e1930748a6446e4e817ec5450a07a01d49c767ebdc711f89b07c63b2140052c42ac2eb6243a4386e4e8fbe98f17f28c3c452ad376a2bf51c5e305904a1357d1f1b12eee2d782f91dbe7891c7255872f43c697e8fd6cdc923fc866223812c568eec14530bffb2987e45f44e0f792b234718307275546dda727789f918ef4897a6b586f9a614187fa19cb3aa3eae11fdcf108f69581082882aaf9a85744bbc451263ae2e71a2e9ee1413403444fbc4cf5ed48e73211835dd7f2eb21545f4749cdd8fd83ef61a836afb24fe46da4a70e8241e81080d6afa07cd3bef47dd96a17e079ebcd81231d0d6496bd46438cb6342b7b7934a42f375a47b64b9ce0c08e21c5050204e576e552002fc90c86e92cd46a8e038a647b3635639dfdecde6cc2628baf8680529e9669eb28d02f1dd514943a034374c14a603327da8f83a196ff531deb4d642513977742745222f18de817fe9bd55c4dc0810b56f516b673498f7ebebc49bff7c73305932e8f86dd79512eb52767154734816624da121a925de9a2cfd9104cd2c67f1cc2ed5413ed2c56ab5634dca211ddbb333c8ebafae42771d9f4bffed56d4c0b1c6683bff51d0cc804e1e2f6b288c78cf292e0840d60462130de3224ae058533b510d70cd9d5eca048aa7472c5df3cd8ca66fee21194798237cfb506ee058319764fbc09f21b46850459cb581ae2417992351339f5f253895cc4251670192824a76f8fb63d926efb1a070e0cdcfca3b6d91e4564e085aee5034a10fa2df175e0b4ef2ac9bb6ce88dc16beab87a5a73350d5b7c964d005fabc58ba0c6ca62a7c127a49b8f01b6eb8aa51d3c102591e7a96029a248e4c65529613f177df501c88de3938c378eb4c71bafb61624c15b8a14ab6c5b0840e0bef1f6be9fe4d469ad7189b3fd79b2af4e9fb2d019f98e57e56d33ee4f32f2d21d8c11fb3190e3de9dbbe9b5c96044d92e684b16c8a2ac216cbaef735b2c72690f7692392904cede6bf8591833d4007c7732e7c0d70fab6179d13ca6f77ecf27e689f7a6d4702d9bb293f3dcf7761dc6405ce43e32e73d8bbbc46c9ee7df606bb4deca8b197bcfc79d6494793c6db02bdb2f14c3b81ab1d5f7e5f9e07aff50b64cf2d82254d8e7658d3909bbc27522ab2b6a31394e925c84b665a4a030d5b1399902c0e31e27733e1761e460095fee4e811c98a8ff6cbb37a27329b9df33df55a22e52dd17dff78643675e913640fb6ebf88430487d1da2cdb6148076f0ee6c84393d5", - "priv": "8db98d451a84d7c9fdb7e2bd7628ec0efe6ba51499ba12bf981ef380195e1d8bbdb2d29e491867090b9e965a697b5e5ae1cf087ce91425abbe0ce0a5af62653f1ac1ef5c1fee6b7f332ff0876353bf37596d0fd0bd5144b2d28df122762c53b0e688bbabc6ff40ca6b59885c172d7b8b03df7e9eb847fc64437129be6491fc9f17844745181084765356218212331443581827422547478716583235137304142402455774301672220067702281740345182635367206821152585408456654052728583200823033372154310824870472281817357366180438076076674475812436718415054614482424484278483046206360807771787771054735117481860335283427845150441828024348673056854648847118566408478657304738565734805614324307071342515464763053856836203744407720261127508640865603645571763504615240651218232156110531767574417578488131402811708672300570030415207614860486716278605250054542784421203140032858080104483743443502057255687503365145364325545780515742727205012463332228222545378481253257774532743251224012706856360000657410838731676482345513625233382538338360685487381801863581234163171801118480454512304805870580353572172486653225874875432158856321508853750572842660701771844633807757246836606614711553870048011642387468317806408144712357547215517244347457800162502560134340120227860884181180845236075730547174351241070547148484732728430350804426817052716534122672621650022564668418360272021232568277144644726668188641422271467488778515871817362810073182218026675237214022420675082370102767463268407376823612174601552176822253665808322107310413688206233547728348046326336582588831571550353146288604673611722768507738570106650282730540010814825386303560441675734048647887803531221650516815166201144723144731234257121763440850075481006600576245770066430232611184655640121061423732475158340280276165264230773851076665813040613203748418653067610885602255487480571513758574384651854415626417420543166747785171622576046385374026360446536560323364081514531124255163224126611340585256771327070023233175712863557000643568748470265527880027314325564436741673163013613563057262677350520653061006868115275687721800851442668541753630261381875745384251303754538638404618280501713206120252623514460810823423805714323631500120804284855515134331476516481847486650288541442660882611657005023631346640283306348184686066537312548854776538144604140728572838456414638133171874875422240152881130760145071162647006611762068256704854336802543356764210411586424602276003305764112061322443824572765215233587274448602602032341352101470571466720431168327107605723515030588630603022537525532211385730001520137417308382054521477265701811070771684871876723563513581351236548745640701728104731485470714068785004725608360521461771588538108418144581302136103731866083078237762606701124574620400076086186400026430204242416313181665824713128874033465213378736357151255754782458148571410206886244328708502561842137167528742821045110640483861757763044035404758481557643071506274125252625457522422851864812233285804123447364523664267670644684325263185521744116250655620038007410050478715435430444716138012661608280614268743443256531360686636133112133285152162217110212444684675883403052787004876652088607383057786732820085417285882c942addefd289558df68f84c5d3eeabc4272f5977ad513d3a8539d23950c631fb6fec0a49a32ea5ee0b732a751ffa8281cf1c1d4a278e6f9c87f64d6d7df0af6de3521af8623512f6e27d4efe4a716fb72f483fc9811832a56bc22612c7daa2779ec83276ac46d188158d448ffc8316e526ce5194a2f2afe14dc009ec89c712c705017e68ea63e9fd3ff5eddf24afc4533190a999f2e3909b93b0144cecce997b32eef929d73635eec938bda1660f58d15e5d9241c6061fa2dc43bc8e282081e324975dde1b84c32c1031987b8252e1b2d3047ebaf0206691348a5fedcb7988ba0d967d7fa8610cf7de3b08a8bb536d2a80c75d74dbdc6dc1383a74b936e5e342e3f425e64660d230779c1ba1aae18001bfd14ee3efd849fdd81a561ca83f31531dcd1777af16a8a7e37280d2c9d7989198aa342f845be6f3fdc99ff6e4a2cd7e5def8d44cf72cfe0fe7a659eca1816919613b8bf2255b77565ca0e332e18959ef7c4e3912f98bcc325aa4341c079a04c0b62050c9405f4e87c52c829c84ad60cb904b99b45653d5bc9b7cc96b4a8eb2bd62282f2b58a2fcdd4f48031b355b2c5d4d940b3e5ef791277d27e4d9e91ee5c1dd53c5f2c0f77d0cd693b80a97d7aaa4ca942d34879430bb0a5b354b51b3d61b47cb9c53339ba44ba39f617e28bad34125090052479a275f9c9f787fe355c4b8e965efa9ec3122ce4abef743361422afb61d4136d5d83ec2476a17682b3e16fbfc14348b2a3618713f78bb39f23843a5fd50906920185ad1692597df722b6c8eae0324c615fb051474185ed261c1fead15086c88fd18a99226ab93dce1a11c289b91b6df0d7466b1aa26880fad838b520ee9eb1753479fb5e9d17440336302a2e3b12a5602eae3d561ecf7580b4308852be844fbd025e598d3e4501da5f0e4e8059ab05388505374f5ef6bf6d587ad79edce255211f91878b4ca75465884c75801995b4f21a2ac32e38de736fd4d1c9c165f4c5fcc8f9392b768206084f4508ade4af5ab87dea58b42f82aa64b03e32cbb5def948a14b6d93881edfa5890291018f7ba6cc7148398823cd8840075a3335b5e0b1c164750cbc43d852c4d1778f258bcf6898e363e368b4dcb4863df4667fa505557c35ef6150e74862ffeef1c42779e870fef08c55c1b7dfd433cad4a6ad2df25a90e840c07d5695af96120bb6a41d48d4121e05fe703b1f5c8343be403bf30868b215a36b9e79141409a0ad19e087e39afac1102a7d7a2411b4d435e4d731e6cb826f727508b0e7b360bd2ab2a778087fc0d6c2fbbb171ebf7a0cc40da389836e895a6e0aebd0bc0101d1e10bd7ff82dfa214631b38688bcf620f7188f33bbdf17ca3fde11c60d4a68f62c2faeb9082514944c93e31c69ba1446f4da0390c250dbd21336667657326246a4ceeab541803f7810fcc2a9136a186319e8a164d25efe0cf08d98eedede98bc226826f3aedf19f5837818514e15960757f5b705fdd106e061bd6777a000169961d5800e5cfb63f81afe396861cf87271c767db3f023ea090270d46e4566533590cc29553316c3ba34655cba17eaf8227c14a87019324d843641d3aa9e08befa9cbdfe9e43693e10e3ce2989ad595b1c279b971cb03b02644c8d205ad9ac00e52c9d66042875ed8a8340ce37ce026af25b8ed1eb503ab1f29eedcec95c1053ae4cdec7987e1aecf5fbb61abccd1ab81c38a674067b1d3d1dbb587be58f0ed4f390f329ecf85eecf686fe7faf7b065d14ae1ac5805611ebb4e24c609add608864fb88339a7c50135bf3b9fd149aabc7b812d9dd9902884ada215039d1cc6dd687207ba91a9ec8fc2c18c15f2a841e2c7539afc58c2f998b8d6f683b786f8a0859808150129be0e57f7fcb39d102ba7346527f6c24ddd21b021835b32e094591087d20e0ca859159e033bd06c7ed6b76d56e49bb8db788fef5c3649197dfa25572301076ae65f3cfe0f135b8784614b65c458ff7ec6d386f10b673b5d17e5a2ce710835e5504902484dbf2d4c99b66821f94329f6159dc50b5f9611356f47ff4ca62c0ba7ea6cff3953f68b3a2c4161d63c74ad4bed2ec2b7b57c81166016141f8684c26b7f7b7a6d136f1dc6669db16215aeb0664b322e339ad8adeaeb2631a18e423bd66adb9da0d7e29210a82f41ef96654032378de32083a9df91d237a69f7895d2ad7ee5695e498d7da5fcb33ed831361a3ab049d36d605e3fbd7f019651467d06e9d8f14975eab9e1d30296faadefdfc435be54a23774d2d34284dde0632ae5bc3ec76ce59675494522aeb4242f296b32d1e8f71b9255d7424cabf83377f94417cb6be226fe2e42b020ec0132be43e0d0f0a346a8451ac76122a44a15dd801573c704e0feb63e9e5c2a7242a1be0d3baf8c887c05e032a4e5cf49c462de9fadf951085420fd67a5e31ad9ab33b8fce6c22c5e3cfe8b87bd3a13cb921ca861315c7714f96cebae615b179a62aef869e81a3a5a16aa6c5a7eb6a7025bd47d1e734818a539ab8aabb6fd1d14f2d92a22a9977c9daea678dad360ec2b7e8bf72a5ef72556251356937f6f515329887914d81b66fa071c538152d75208b58bd381139f5626f5373a6a319eec4c79a37f759f27cb2cb76d18ccf5185370d3058c9b9571845554bd64d87d5999cda335e3f93aea99588f2bafbfc9dba476b06ed3a57d8d913c46fb9734a4b5ff97acaddf5f6e08c9273f712639633a04c7e7b7cef00876ad865f2895680a808ebbe6e8af85eb2faca81c33e4ae8097a9a003df4161640cc96506f42227de85e93177100ac01f05a6e5701fb8841dfa529b35507442480b00088c5c60026aa77def2b81ea411c88ea6770c5f849528eae68f1d83e2462afcfa372241a988e0738514aee3f32723ec78efd8c04ade28291c309b2217d251c19bdf9e051394414e49af076cf8a5df9be6a4c7825839f1805d3da89eb2071b9e2486fbeebf1a5967f1ac58a072901b82dba4d6090e4a40020590351837eef6cf6e4cc678f3faa67be1e16740e7fda873be73c71add485001d002cb3df4fef3ed277d130bf66d8c4106491448c10b8c402dd50c95cfa53cd8eb375d64e5e7500c66932b33e0a1a1433b8fc80d0edb37004a2f64a3207512ca591123313dbd5c0c5d99475595f2cafee7e9bb138e518e679264d977e2320cfc59f467d889b5b4d3756d532c61beae3199ee83d905a440ba311d8f8b7529cc0350beafb908bfd7bdd542f6ffa460d2116008f16f0471157c117982506d82e13a703eb53544a8783484526d8251628e1020dadd2f502a5e70fa9e90bdf1cb9899f79b2f24bd5d09dfb876b1845515d947f8dca2eaa40820556d16bd93382dd3283d98bc11cce2418c43a35e07ab307766206c0f137254fe736f15821e3aa07eae299a33c31c896c2569bd39d2a0736ecb396fa4af9799180c693b342a56d7255659f75022e37d301041297377c228a367a8672d0faff459a0da9c40bff60ece85782e991f0682dfa73099a87ae293860b143ec788148" - }, - { - "seed": "2d6ecbaae0e5a784b543be58a0650680ae813a01c7e0c9fe65ecb32a304dd218", - "pub": "1c2b6801785dcc358fcbd37f578673850cad84efbb28ecd828783da9edf6503bfca2420ace9fba45d4f39487658c0af41e5c876c107b772c7366b70df124c15de0029fa1f002ea566af04441d7c7e33dfab7936f19f34a73aeaf42026e4a7245d6fba3c21f26edd80652442522019a72e586bef8c655af4b3e6c6ae8b8678a81ae39e3a4d756af595e15aa8c4adedcc4e5ba4f8eb4ab5bcefaaaef15a629fbecf7bdc657910a62e5e02e3fa3f1d7fc4d94ee56f252b53020e325c25129c5c4501fded83d071c59fe6454aeb1271161dd062d0308d1c515360e3de60c383074944762ea6464c175f7a9d317cbeb83a8238fbc383f02e299ea185c37f259eb4bbe3a9b26353bca9a1d877007a48b1be4acf21af2b6d1b27edd5c3dc2a77a17c6ec0a9988f2df6ef5087fb15d482439d26cf63256ecec16bebc92a65a112c2a277dab80a0fc49a18873f9f62e48e44be451c161d5df260eb14ec62083485cf28ae98fabb0008feb12b0387aa1ba88e70ca703f8e2da0f7de8f08419fcbd0a5c120081e0f57a91857d476dab4bbf70b3bfb7695b48486f3e8ed074b258b930c092f73d749e2671a9163f631b9ead06d631bd8325b4dcb40bedd67d9cce14963c5d4b2ead21ebeebb441936039f99bb12e5629d5959dfa5627335757a6fa6a2482def787bfb173babc595df3d03477f8ca89b82923799bd5a94329cf9b1b950260caf3152441b51b576c5ca9213e8ae2b34858bd4bfcc5642fd4a65c1f38f5444bd0fac0c24e6d9ab20791fd3ae3298cffa4b1f2c113ccace75ecf9a83015c83ed7c6b20fa037e83529d8182a16070c6af08652ac7f4190bcb569a7ba00baee9fca16d9b0485fafb55f048eaccb80d72b34299c9820c0d3e06ea8b08f844d296c180d7f86afea7355bc0b48c58a65c55f7582ebfe9d23fea305b645f31eb1bc7c158f3d14d74101973fa0975202ccc83cc962b2852a409e6c757427e9309746bea177fa23ff5dac5abcc5f85a8d87861104b41b04aef79c31c907f9774c06c2a4cf36c2e17829149743455e419e672f744c3a75df01d6239e4492e643cccef324ffdc0e42e531e28d98e9eb41a5906bc6ec0c4b41ed82ca86262f768d89a3c8860c18f1b42356adc9c1dec2a311dba00f7e24688642e75c1325d4f72619535302b520660eb56bbf4e7cc7f35ee8261d3ad2174ef0f5b5aaaf9f664b61ae18c5368f080a9238b6d4f4047836c9d784b95b84bde8aa165b3fa5e582a2f24aefc50f1dab9fbf666e4ecc858599568fbd3cf90ef6f23365951a00f808ad1b8b6ec09084c97268330a5e24f4f8f5c73d5c365a5f88d1287c5e37076bf79d3ca40eed1fad9dfac8b7a954cd58bfb24c200704e19844bb47f5cedb184af2939341d28229f63eae74d1aa2d14550474247fa3922d2c24e40a5f3a765b3e41f0126df8a494f8c8eef43f05e8aebb1fc899013bc21b764c33cf4ede643055de39ae5394c570646828ad265fcdf37e0cd152dd07acba5c28e57bc8d82d871c49c457dc3cece1758ea883e0e13166e4b82262492136fc221a15b9725647b10663abf3a3b589a73226d8cdc97b7ca86ceab4ad973d83f85190cf0f50938c1e11d3796ff3bc839308c3e8d96ae71239ce9c189f7f00db181a95a5f59d371b3f238f456d736af7a948d9cdec9ad6daaed77e47aaa925d9ea0b0b4007e6fe9078cf127729ad03fa43789f38d7277262502d17580a2586453b1c38a24c7f5c59d96500ff01bf04224a9a868264189da9cf4f3508b145ef402d217ce991419b68e5a82e00bc46da3149e392d042e785817a41e33c823f4c6d2551d5eb03e9ea862cd175d58ffd1b5d7bfd1c7ac8c6a505d937a36c89a60702b7f64345d13d82bd29c86302aacd1b1835186c5f3f56b9e44e085106cc96907a332f0fdbea742a6715bfed95d606c9f05b5f37f8f51bb049ba47dbd5ebb80739817eaf3f09810b00d9702a91077d60a09e7e70562ea84492b9dadfe4b8dc957727fa2296a97d24ca5f065f17deb081395dcf58033afc2f424a0ccc3220c477ccd627ab4e1d7104477d799833e2ac49aae6d055c97d32391f7c138daa8ca142d33cc035e4fabc57f3d1b0d8f93468d08ba33be80c820ea5b3445b4e07e584b42dc27dd24fe42da51b410adc3d8ad3b8fe21c573858efc0b6e709f91d86f6360c5b7f1f98a4b7d0f606db60be93ceaee79a2112a93d0d6581a58abe136fc6a87a6ff3d993020a6e5bbc682bb2175c5e6ac38708be21a501e515cdf4d87b0d1c57ecf232936a78c525fe54557695ecbfd0b8751bc299f0b8a98979960939a1c88f3553a98a30021d27c72c9b25d274d642d50e0b438a65a68c6a2ffcb3d0e7cefe9f0f5722e033f7358d7710d18a1bcdb12e4d01e3e8a580ef1a830da29207acbc45fd589270a9a82d7e090406c60df24886e62f3055cf4e9e2d03400475d226228dcfcbf396868b1e79f91adaad9542caff5fe3483d51ffef8cb247f2e90f489d0066e40bad3d00222047bcc934fcbb4084d5d6b0397c93decfbdd0d22ccb2a04aba3ddcf8e6bdc4bf271ef1b55f808ab58cfbe7b8d27d334f0cfb0e2a8e3926af6b584bf746dd8e7106eb4d0272b234a48707a9731159ba9f772d1bb885a8be43cc527ea6f304d1cc25a41f876d393838c13d3fe8e7b1232dd59c553977d86d2f0634c9061cccec779862398d13753f046cbc1c6bbcb2184d3b93ef6307d094600520a13c9a61cf8f24b966f33a4e1d4a63129b", - "priv": "1c2b6801785dcc358fcbd37f578673850cad84efbb28ecd828783da9edf6503b2a3d818fa1632e882fb4b102891f36847d725efb265104c96c6249d614ce2da2fd15b9a2915a14f0f18067a2ebc07177869430c6a3900ffdad11eea8256258954c53cdc5092e082b959cad36e830534ae598cb9a40805da6afe3a33c781b67682304811862666262674883630257466336654176127111610188405651882248835621772103713057301461408544446057187771006674605835060402676635418131476413436003120645277455515485670383644331501872624770716378003605043343662173545134662807012482221028367326430336535664448056113574018581120523841166041143840318651156482606328312581566713531544126481316674737206548863641151137443513805664368650232741372866237083842038500867032145440548358704527308541843850274876810732814453828163568433334252171168355156128245552322375020411688726150257732451832171850113208171275024208763087043620431368784852342633345325381082054768367221670638442265455241150542031786524420340504232434554630307202834160338843770683236510173416158055663006632524311202770074186756864725651225115207874172102767108723215410126544502265753858458031284223785244845208708477813813164616574044334063467141642437824662515130780320530524304615455323331052410022757028285822155463465307887721528548442757207157143662703603322523164328585723017213078884661343736471304300711110210007661410452167826762283616602211111814737670478671581647376618273266215607470650400468274107273140772805621181485466005826678168630861123665356648222147531357331816374484742736281012353528830064601303473326670343601815332320656614136537004121661334847127484167341210426215347444665228633775855605113481362562501604066143748138675085214380117534354518528803214733100542576016451870144542343240477121026665084103270221073287781215258026275727484778353836573535212634148130745855242442608642460711873814258078850618877672413774513172426032072356862074508810306014067080867427757824824028824108174406026218102520624880108734712762825145441131055432206348270026562148550718452404551485343104823587357361075363067777608700730787068538524620734084330357617168267260432467052780270082138751130213247302351083133755083746701327633651771612817385522241687365428627888010160240244451556860642616888021741676615122361567710825223512105410650126041326541401456171026106665284806160355012356447348246653058504148285820087475110160353520303780551734644523605167821608646410237607101761118786078003148446280063422132668120564163088754007557568310505200680472867527162330302442631523115778167707572822871262554364140832017606753138334338852737720140605628627473251125862002613337020675245162661260861007155034720455157108418561023828220700355382181424101273721445815451858423724440784253713785183511880022873741854405034651712631638575532026648282103088505253625664346403781263188161174460770820772032382661577887440223154505470856385852111666161268622021383012686823504876281517266854274311810301526324508130485562286633448201880388745815358336710062432506786440757406072140568841501477456514813456204417571574122527482775515235688833535654757407187843821823872746421510747450775537360482055485647333021465b68c4ec5cbd1447a46d08aae37528e592c1babbcc9f5fe65f159e1c54ad88b07a7c424748c63c42101d44a8cbc87510be76b9f61f3314bea466b2f7ad9c7831dd8f077ecf863ad498aec0735dbd6d0a86f2dbe80487c08e0e15d4f7ca9dc09822e3a541d65a07bb3bf9c39ab410ef2c0a2f707985f8dc2a72c9269912a3282d6d0480d37927959bae33003b5a03a2f82850bd15266f977ededffaabc2b0bc9ba8c550b5d7519806a574bb1402812d52d6133845df5ec6172352c2ff5d258d3d5858a2ea5ee606a40cb2d76f461980816bf6a536a79d1667ae5422346bdadbe2f6c70fc143aa30f4c154e22e5dcfcd641ce01eeee50f42ad9ba102fe9d8a186190a495fa807a5ca7552b8827d90ff2fe48f8f195391e358754a3b032d155286a324ca507f16a815706a3a5a1f127e134bc5b5143659e4601212a46651a4c7f8823af02be5e3e04f41f47259c66b131850a7d9b0dbd3a415e078625127de9f1d602dba207c0720f3f96a44d86d60802ed16271afeec041fa8aabf92209a4d9e53b311956e46550e4326a5c50cca7aeaeb692176dbba39c51272036b38ff92182a22c4758d1b865c1bbfb342c1f9407babee19dbfe046e122e18cf7a25fec6a28ce4c33c121ecd9316e9af0016a16bccc46cf6329d878f48990351829be43228f200656d57813ffac51dc487a86f6858fcdc46910024aeacbba199ddc66963d914e970ebd38f18efe709ba2691ddc8cc272095302bb2d25657c32bc64915575b173085d920aeddfc37177b5fe4f38abce426ec46e0723e00982fbe5c7e8e5a4f26540e37dc39e022de7a08f13b3e9f88d05c30c8970899e2c3fb898cfbba00ab8df919fa51cda3e8193f52b8390d7c274c7f5a344ee42312b823db36bccad37c4b213011f0310dc9ba72b851658ddd5741731f21a6ce7f9059872ccb9ed69f732b7410033d8b5acbd66b33928e3a7d7d5a28e3245e883a2ad84f7c2409aff0402e982bc95719c10bd187a454defc7d3693ac537ada62be47d6681667ce11f9afcbd8031f92085400bc086cb4b61fa363096df205cad59f6859667a9bf44888a0bee5d4b63c4e95aa59f02c2aa9bdd02519e1758ace89aef92f32789656e071bcb10767f2727c309107847de2a0c06360daabb356c35086e4c95ac668f0f4760f636754879ced6a1d569fb11e5efa2802e8b1c8c3935f6c5c097b96ea478143c2d2ea5c1e64fe19e03f180b70f4ea91fa327ae0ba6f4c3179570c62c10a7af043be2419959f53a31edbfa1e091029f96ea203bf98e6798d96727db60909c09a9339fe71ce9e4da0be641f0e8e53b43277ebfbd0682459dc028c6f7c042c1cdeae9dac9511e6ede9b4927454ef9bd651b233606b644bc2da0b29500b0890d64cea0eec968146c5e5fe395087bb4884f0206455290ba892b0d929632d098c33c8d6e27022578249c9dc0c207409799801ecabd7ce84729884e8714a19a05b9c7c8e6d203400adeafb0ca2669c8241914f85186ea0b50ab4ff646c5d386fcc3f4178ee18bf5aacaf6b1ecf1f5f894ade5fb8f5ea336bf88548102eb3c897af6cbdfc7a6f6667e075475359840328bd9131d2d17fec3a9034d3c7766110ea3118161a42d3b61ab5aadc71352bcd0b5a1da9cb741f70a6ed9efb8abd5229697852ac27c189cce811a9025bddda939167ba717f1c3eaded18d9fa05c2828673af274488f154b63ffbd853afa274e182d83d37c97c7090bb9f2daf9b37862f846c46e55be02ac19d23ac0760e2b657c0b1b134fff3c6753f96ee8b2cff394b0f5b50cb77e8f7614664fb3f0ea8ba85d45582a71f3cac0dfbeef6848c63a270de0d2696ac4fe1eeaa781349b02614db517807cf4d2b0ac80ffbf0160cacb94f2c700d57e156774d85b52f5245da4dd8e4fbd2b9dd1b9256fb65d538582ca08c20c289c5af404349b12e5b3a431f53194e894a45f7ac68fe4a0ba8feceff0749ada4a9b87d52563572f1b0594c62586bf28a821de955696ac76565861f6f44a167534232c3eddcd921f5d939284da288a8233193b231905c76ca822b72fb04c21b4d7011d4dff88544c1408ffb8159a597e7c4184bf2ab570c9cd7c0b8682ee942b864a52f4b71c6a79121e16c40da0ab4718fd859598a4f52790835a5d87018339c221dccb8011796ca373c9db8ee2926046b0bc01c4cc6bd84e824caf382ebb9d2be3f8366100116f0234cb3c53cb418bed8b8a530cfb64832c78e6fcdc31d830e894da330737c0d14eada335e7bba9e270751bbc0d72a137f3496d3f4057428f00c5e8a6782ecae0e48c3b0d1220f2738ac092793c18fd30478b57bdbd2c4c9462a37b1639163bdad2d9a11c36467ae1906dff0f3c5a7134d09168df7811fb2418c43d576ccc191f0343373ce73432735b178bb122a9a65ae84b27ee42707895c6412a4970628df736082d11d2022c08c2759bb086547148c885128882c0d716db047a5821bc1bbee85e4ab3c5b8b40a5d673ce74357a475d47e96ec40337fa16c6b2fc3f09ee71e7fd4458712112412f6549775d0f66da948e34bdc30faa8be5241d57c48dae353ca3191aee310a055850a266e04bb78982d0432d84531b0b20a2b3d238c2ee1556468a193a9a032657226ac726d9757641829615989251393ce0171ab29f94c1d583adfe35ef8b9859b67364dfd3ede5da27cf277680c65c0589cd7f715727017f02f14cd9622468df17d5697ac895ae8d46ccb1fb0da103ae57a97f316bd0179b297061f6286c07294c55458144c6aa2e1932388362559f28289b0361ec79a8d81e6c77e7ef0d3327a85accaa082862bf5d99dfe89243125a9bd7bb2fba35db442e41e1db8563f54ae40d444974307f410cde68ca0ba9b923f82d5f181c141f3160a0450f57454fe6de530f8661d49e1a87883003c5d1b83e0f21004e2648970e3807df2b865bb961242943733938addd5d219b7fbdbac5acf5ef250a67a0923e8908c265876e56907f71ff287a6c16f21f61424d72f58cc468d399045f32083a17736a99a263e976e14492a6791e1ead4d568ac062168a7e85f115cdc302b567e66a6fa7be6fc6d6f7d4e8751603079a64ef9e46b9eb1dd50d94d0d85cef2f7bfc58b5bcc193555d4b83d454cfbc2f910ff7d6e22e9a27bae8a95a229d79c64bbca7f563da32246bd8c7b1d5022e0edcff163b03e4a3cbf2ed74409fa652d82311a753cfaff4d9ea50bf7d91212e60b23424c90edbae25f0202d71cb566d6c4e5106c6d618b8e49add7156561d11963d2a1dd17a7c2c00145fb0ac9673788d8ac7886470719e405bfce819a7083de2d841fe616078208ef2af75b38a20c61573a4094a6826dc2ae481a2e3391260bb9f01075258b7eae81e2cbe387ffc018ea827bcfbc92cd49ed433dafcf00ce55812ff8fdb0f566dda8c6f7942cf7a9e07e2bcedf02d2aaf40a66d0a55912f32a1f1d5c5071dcb5eb86cfc576791fbb66b5f0d38c9d2f2e31f86965acfe661a9954f3fa8e9652988d0d2bf72" - }, - { - "seed": "3199830796190c3968520dad86a85b677558a22257e43459ac684b68ce336da7", - "pub": "525654293354c2a1b9a2a76c9a4908cf2361efb2312f8751932347fcb8153a473cf3ea6aebdee745dff2cbe7a31edc4221052d97347909f0567abf97aca00ec5fb1d9044a346866b1d7f99084c55e01687d6482390ff78468628d011ff6435c1a0fa157a895ae77b1745e49ec365f051a461980c4a22715fbdea55972d41fb6549bc5085e175042cf5554c03d4179095625449d7ea256949e94469dc1e1bc3d5d91f2dcef107eb8f17efda721ec1d1b0f6bdd2da9f4b628b4d467584a1dc37f33d4ba326a6e783c562548eed4891ddb715072a7105cd1f65d4e5cf147896e3d16afc221cbe3abbb3633709a91293da31a0c351c9974731fc48d72bb69ba69a76f06ef17e3de3818570809848da31ede05d9ba734f898f38058c8726b8e08a22cb0f07482e4e96cd9af73c9a04a16e3dcaf2df45dd49eb0aa4b0f263d071141c0aa08cfc61caff95ab9aa4d66c20fcef62f2e4d7a85ec0e4996ab14db4130bcfed9c9465bc93d8c424d1904a732e5a198d183b7184e0be2123a135139dbfe7721b5863b30f8a99fbc5221f1863cd22bcc710632b300c8a667c702e091807a3ba8df2a96a072c991673851b0f30e0570a68be0d1aad7910e68c40c240a6f151b559a970a1f10a81a91feaa8226389c9378b178bdc69a4de7aeb439007741eebb06f2c57bbd01d80114659939715c42e7cbabbec944e40129e4c626a53cb1aeea0d4c1ef556a9cdd6411010227cccd4bbfcf634b2b59fc7f51e42af50339ed2bd88f7d7840cf2a26cb5f64b1cdd1d7671687400219f4291fa480134e3ba5cbc8ddbc463e552f8f92268962d97154bffd77c061ef9c14d343f49ea0ba241124dd41211e1b75f6c0623cb0822e5faf8ce10bc07e9ae9441bd50f4ac7d79846fada78c9793a55bbcdecdd98ce0a669665e33e0a8a142cb338d05ccc9f776a04df80a95aa00775d52803ef71a57732657eab19493c212f9ec961efb24302f32a489624cebf07f23dd09412045a413c67fa16592c8bac0c98a5d5476efca9b6bfbb38e87d301579f8d8ad6daf8b2c6b9dd026c19c931c42ff9155de9d0959f30e04463f264ffc1589a9dbae3d96e247925892c230a6200d446fdd0010babc17be23eb98183ed8e333ee2837b43895e5378d3be60136696c2cd55dec42ab817844e77e430964ba68e700b766bf046655954bcb9685929c018b0b3c7747b8cc37f1141aa9a3b190e46578fe93da3b44bb48f339c861fd4f97ba0b0b4852f839785c542e4151d9944e26a131d5c248ea31c9f41b158f8da5e025f3aef3d2a15386bc095fefb360e4818bd76446d5f0a72fd4954e5329523202d7c05efab170d185b2bf0d32bdb32f33a7460dfbc4abdd929ffa5fa21340a5ea68dfe1db724e0e9ff2e734fa6a11e5ffd61f086c90acc6edadfe8df68946901c5ccfb5a74cb6b9ce8c490709b0834605fbd161839568fa1413571bc7b350f78f48d23f67122fb629de30a85c594620b92284766f9f2664c7dd414f2933e0e62c0da5e48a8c82e34d66c559d9bca52a06e55e42817f4b5ac06adbfd3b06433442216e47fbdeda317c50e2107e8d6592c0bdb963dd4df016102c8bd78c5134e9e120d0462606eb5e3822d00d235ad9c7a8cf169610c65aad5480c45e2d9d95c80adcacbaf5857f86fe4cb5de389ed1803b05ffe13f724b02fead70e900f3aed263624af0eef24ddaef803aabb07ea37366323b6c306e77b81b00b3a5823611c803a62c9287a09035834bee86acfda3ee3a3fc69ae707a74c37cc597afafeddc3490e4f19cf0195217df1bcd3e24d1be5787c6a08369ec6867593388e2cc5677a10ce6d9af6c0fdd970f0d484f041c5a4c2697f92e52def895adb8194a11711f055fb06c5b9137d446afb847e562a1f5ddfc6f17db54dc8fcb33c600ec7bd5045f8eed910d2d19d14b422ea6c1f31d3aa272c2d6e4635f38ab155fab5c8595f5a1abd240150c1d20da320a7702a499bb3f51ae6dc74240bfed48d152fd628e7b2854f894718d3b5a94a887b12bfaf7456c418a83356f5d0ecd7ef4955ce1079d4781ba21044e64e71ce375b5ab6977d09957daab44cb2b349670b11c3f740e85518124332eb859718719e4c3a7ec3ef474c0f4eafd0c104c1753396e8df1090e4e42a4900665ba62434d8f1d3e3df25569950e401205a3a8649853eb34dd026d35cca312c5d05842d2744b643728053a93eaa878af045632c4da0986aec5f4e5e0f93dad38911a8307622a2ee9fbb93ee62b7f2d90b222ab0d23211e71227a2152d6dc2e536ea0f8118464a9c8f9b1d85d6c10babea6fdb2262595687add404c4c15c4c2189bfb7660c5cba279eb6fd85a4c5276005c7ec5b3765d299783e926124597132d7eb623d665cea1db454578985e785022f680bd1439aafa60e90694cb720eedeb301b9e948e424b5d5b4e6d976b6e3bf31029f346024de71ac2c2b42105ffb6054226fee8a80c2471c052c3c07d6a4cf749135e03a0b263576f9f19bf7fad0fa16f39a3a8c4335b0039a197c12465c9c9d6e5d5964186fb6fd7e7ec615f1da758f207acaf8b219b256cdc6b5200b64fcb9caef6540e2b4d5f382c9d8682b72f3d359650d74e69038527a215221980b30ac3c066f2198f781d1d318b53f0b0ef5a8fdca5d1b1d6d978cfa7d8681e2bdce2b0d494a30d7092df7536b1eaf0adc98e00d9fc718ce797240cf4e3ae2b8aaa87af2fab32922e4a87cd267fa2b6f1ca38f4f5ecbdff0c879e12", - "priv": "525654293354c2a1b9a2a76c9a4908cf2361efb2312f8751932347fcb8153a47ab123ceca94687f65ec4fd6fc892101a78f01026f29e0135af71ee700e7c2cbc73cf903b7b4888927c0f819c0ca2edcbd907067803377984aa4ff3e17734478a57e2b35b766399418f75c7975acd04f60063f2f0bfca26e50f070b0a1a195353724566837267013523843061217340448208603377516427785068105543815455713385838378638182068387137202878174761230078700864648646024855062224860686668854027226160574716084705654107343266361631364842553385601555588856047580535034530370012175508353073724842155863748067168114848882320522407062271240544578230102367855236538671440435531266463107672883753384543572436706682450834316033375243560363701823084801423101304218866444185862300771604518682156827233004524227545010242832663758743810826325221807752832476605018480872813137847777000653666127557527716638486160042404864166636102870313548832240045178714184303667865718102217306530807425665255147226317774324026116685410151810861754650667058078686427182806416042711402016888435813707675336867138675385874877012367321122252527373105272488877008643087733704347456662422460586083063645404228215715050611018103186084667757203763065215143246526035450665527055616815808787430678265678120245012578311308256263333860323880466256476062110526427163351471203052665006541664736828465247818142306281443835837182183652107651602852387576021550653670563332605536365174537158126383246523487401623134168384464856206204768217870623261824124585771546525528033177675181171075524844712203858364348868366630338263454740137745641040281333252087128027252246866743284811231073882131764045468851375840422556572064517855348352776346620056667224700385762102065606267611202427345130114347574537103157673262766574536203507836868203424662260332464514814176307376835282323336537583824722072737215563716516622534570868515740510531360567302685310330081808880645123531722346410845162360657713551527237544415554545544676603556376177653716885147033372853404163258617884540527813328211514033674414257460047837602245324068143272035585220146643616441718725600482680403063464864523457642605402244220645225704532847633875702715808568343465273572577521166715627587343885578373673372766332716633554116600462443030006236252146783520750515425417144815346847112732253776133677705301441278410464448741113474825577724608565567664387072414188665482012132181145627744672156457615822101260650685316686216446276142280271565741485500215068572175027842512176043780617184765347663010028034833058116425222513618208124855666167843357777361347708737016118061814685808301052444558752468101207730047385746728811752708526513738756226634713860484428284725564228166015837222131614501433104081222168277767128212721462486143511455718342443083388355003610147772667647654723627762544342374672085384358876058841431863634132804448410306706760647544551074056854262848837436080043515363533205588831716267387132602472322688526176687873184770211636173375004366841185377208728801202224543227412038046055442545283515488671645386881814722167054187675850246200624520546261410308840183184005181485267722758628353566744521701762386445637465210013676767755bf422e848963e128a6250e1ea8cd6994a61ac9a0145edf10b3f305466e0ed49a068336c98b0567f9fb23c5a87f7acaf7f22a9cdece4215215b168afab7821266c858a92579d96ba48bc94a120657b5c60ba282a2bca3349c13c2e56d7bbda2d0dbb6072fdea7a1d8fbc9b9d965e9c8dafb3dd8ebf78bbc57ae218800125a80765173c6c95fb23fff90c87f7f090758a1dac96da7537b8ce57b1e313312cb26799a65e9aaf0387d2ca3dd5e348918b7ca888e0bccf9136e55ee70903a2dbbce3476aef4cf338e7cac5fe067e23699fae85a9efd9e68242949786ab2a2ea82eaf8053e20953a1ef07bb9e22d7847d9bdb6a06a09948038ba5448337264179180aac89158b68a6cc91507e552ac1dae3619fd2fa2e0cfa0c2489b3c9ab4facf1ec5bdfd188bec71782aa4c3c6b0c6097ae93c7ea5920a832f6536cf5e81d1a222b9b936d5b57bf539014afb8ed19b076d5c3ec355d06a7b56523273ab4231a4dac8942d5ddfd58a73f968cce3a8bddc5d4f703caaebbb910c264ec2079ff75f9417a97502c91ddc2ff5625a3c535c04c8f95fb0b557b6335299dad717d21a9973433c5b11af908bf9b88e4b1941ec12e9bcb9f2b2331b7f08b2eb04fc30cd0a99ed2cbbd3db18e32cb5c160fa885edf8188fa8716c0fa9232fecfd3ea34330a61465d4e10c25497bbdbee15070c3ea66e172eadd1dc7686cc32418cc26af4b2d61259672b51d6e86deaf4208f6822fdf28d4f3706d92fc66ebff9e6afd36d2d18f25292e8175ecacb7465fc04e674ecce3a62abecf9c2d1a52171fb411fdcc893c43c6cfa94b1731f21278378eb94ecd9774054f2d6dc682a07980c87f6c37d3c0822fa30334b90da764856bc84cfe131172e75639935e9fdc42027907fa20363b0a32c7a29588c003df13db2ae9c7bd6682b743b7919de78f8e819376c1d9e64fd1ea0750c335f56e9326e94107df6e441ec38507755d3c48301b616782a1f4abdc98bc8585a18c29e80a32db88ebc3959ddeeb53638f6d58b58888ee0fe37ac86148be1defbbf3e5ff194f9538044036b95639dd219592f0433d695c074ce6e9710ff9c0b1d6891abf1396b5cf34bdece6b3f559b1d813cdaa5df038a949aed51dff2c2e821c643032fe6dd6a74803e2e2ded13d446bc969af4a0bb2b973d5cc54e2aef9896ee166d807b0e41353d6da28d8f5fc2f3d991ce68aac6dc75663323080d5688fc6c6dba56c033896f0581bb8e9f0e9e3ad561490fe9b8702d9fd32b652c7e7b74b74a489b981dcb598b6dc38a7cd69c8f429d1b2b0c827d8aa31860842758aa1720d87b23074dd0b70601fe0c2ab6b72bc4fc836c81efd49b94aaf378aa828cb90242448101732633d0e68db2573588809cb76a80066109f6805445f3880a4cf143d02384a5198e84796eb9e3edee3c64de761dac094b05a4d8981cb54b72c317e4ed791c49159a4e4e8c21f869fcf320f90c0e67b0bc2ba193e29e5018213c1ae8e9d256d8740c5103dcba8eab450a6e259b334e3448cefeff100d03104f810a7cc5d085fa80f054e4ae67ab242545a818e4ea1f3586945c3a4d242ee5abe14db6ea38f50407a88da116d6d3bad935a32817b4a24119e9a103fd7e6fd5d5e020eebba1390e5151ff456669e4c14ea8e7f343769e7510aa68d624553abfc6ef2f839aeb4d6d5e1fb57510d3d7a7f0ee969ccb11fb023ef279faeaec6cf377b524d206c5bf4e529c315e6f23d9aa4d8229f3ac1a0d77b26f3530c80eb77a55f45ab9ffb9ffa8b8ec28f733bc500bd684d49da1ff31edcd20c24231086bec40e937c2ac1f2d4c9ef4d4274e9f15a6f961820699b40d0dbf4d11149e5696652a75d571c61e8acb9ea96b5ee185acfb344c9de2eaf7f956f0569766eea44ab42f0a2982f0957f5c70deb7248f6ee23d322669e2fb3520ce9fc98bf79636f5156d9678bef7b19f916a8ed1f7ef9d34ff853923cba360b10086a64be6bd6b52a90ec48d763c5e00a9bc0822836e594aad9bf91d0945638b6c6a961df953f69c4dd75799c7b73ca6864746ec3402bd341cb14eacb6343fbbd244bdfe1ec43bd6a5a0b1d3fe2d896a04fe8419df95a691020bf61d214e4736eeaf25ec01304e6cc167d8ef969b8e2ed2ba6f5328ef83903c73add97cc6ce4bca6db63615932d3d0865ef837e335bf54ab3cadfd6eb4a7ab5fb441644ae5748cce75157f669863cc89930393083d8bbaa83735de31812e471b9858e267c7e646c3f204250f8d4280494acb87d82052b0be33002806912dbf10597cf46d78e8c64e648a0bc8a756d8f09d1927b73385e8e8e960ca2f3679ed81b0461706f4864043d5df4e5ca59cef9a484513c86e2ff44c496498ec88c0cc8bbfec45c9a9e233730c4336a8d4da876be797b57635a6cc532ddc701a688ab712c8380cd169feb3cbcc1004637bcc616b7d300400b6c55b0134fa2d6b96a8aee0a54ff88895e9a16ffe4ebcd308c7e112e0fd81e64c08239bb95d52ef32266668e4f0f39efd341b159de7c8ee179a223d398ba70a07b774c04ff711ec50b94631be472232731808291aebfcf6894632b1c1ab119243043ac5d0c054b60883d2083564133fa82f3a46fb59f86334be0c6e79e201db85d35432bd1793ed3b28da8f65c7970dcb9fc6ea0902e9b83c4c8ae86befe01d3d5dfbcab946f017cb2cf63aaf8b65bb26c8d6a5a73c9daeff2fd482839916d9d60d3919607cb99a7434574f05fcf15f4f4f03293f3ef2f5c493cf867a4114f134043c5a5cc26f8875b6170c787fde2247de3ad7e80610f6cc09f58b66f6dad4354795d49f994535b4424244f18fc65881f9dda7900f7066b3cee542575f13c9b0e3e236e0813f2d7580aaf8f9e564a3aed65dc17f0a6eaf79f4015acc811f5d2145e51f72a1680957a97d36050028da3d3ffe4fcfbc223ca4907bdced64101577e2418821d77efb9d868fc824d7be13a28cf1eba4418bdbbbaeadb54b3e162deda47fe29c993488d2b5e41b390bb4895a49717babdfc798474e852cd8b573e960b44e85a2174fda806f97a991bf9cfa8260d0ea441a032dd91a24c2ad52f3b8064226b22c73dccaad5daae55e5fd30fc31a43b022d997e14e71d3de8a8e1f4027324e22e2a7616fec4e0acdeddc12c04a56b65f0c00a95b8c1de9b61f7c589d0d8f158e5c9c65439376e5e935cd7b149dc883fc602370d38676571ca764e6e5a2467ef5e775336bcee1450e0f978bfa4a0b4cf5a72c259fdfb18e54425ed83e6de7086c5a175729e38dde3b46e751af79bdaf0325edd7ca791f4f760fa7279a7c17caca8dc172e47362f90097eb36a8cf14da378670639d239bcda3a8baf29b12803cb26891e4b0b24bc61066a490078046f000324e5186c39efaba39c5ec4aa8e9be23bbad6d7ecaf24a5bc0ea0dcdcd90e17eb7b90ae56d12420786f07c8f2ef7944442ad36e2abcd1e66e694d6b949ec2c5dbe99832271f3a70782ce889a55d93f78bd4f5fd19c580f456e684644dde65a045d6d64bd99" - }, - { - "seed": "e788f93db12eb4db91993c6636c009d06d503d5331125a2ad635354af49ed3a5", - "pub": "370d66bf2921162f6025f1784f8ca45a58e6e72efb8006078785bc023d8cdaac29339d545f3f03db0efcc2ad356020bf1db8178b123ab7222ff4041955e4e9338de146932623eb6517bd73687a51a67623f79a36735ad64d63641d2ad2a040e8ce85dabf03d47dc9a3e98cb8098fb22f84c370d240ae0ddd46369d02aba059e31ddfd5f56fcfb2cb7066b488c73af6958dcdefe66fe5ceb0fcbf298cf576c48f3a1df542b5343ebc8f2e80cfe4a2d31de6913ee5962a889dbb22067fb377606cc1ac663787c04ba8c2bbd0273d38d71d18bb7ab435544535a60271b3b2045636dec30b0727c3c527f00ded0f08d372bc985f3c8fc12e1a46fce031d8a2b5fc93edadd15ee8431435a7c6797aa343d33b57afdafd870a643d927ea85c01cb43ad709b72f1909df60499b75b0a29445cdbd1211eda6666695052e4a80ba3a4b22c33b40beb3cab8100017807e5fe4ea49e3fe419ec2a86a39631638c0122728897254a58a4571e31b46583a8e37aedc5c437e27728b1f14cb7493e5698959b6909ffe54a0293a754e34b335703da5d99d6b146f4c7118a27ab8e1f9dda161f03dca0c6408da273d5517683e5e1f7b3c2f29aef73f75f5e60cceb99ac5327f168a283e590e637d33d6535001492da965ae977212056569f2456c8f9596da43989d9162db32d8b2b989000ed4b3b9f87d1251f5fc9ea71780740761711e74d7efab8d007b81e848cd2493117d3dcfc2bede8f85592d8265ac04b95282a06ec534e056ed8cbe73dbc07522e1e03e160227ca1ab5cb3f08d7baa56d03f9b7c12ddc71b69ede3f6181fe721a75dc0931c11f75d08754bb461f4a2c6cd584ab8419b7bfcb7ef2e39d8a4c1292ae9528fef05c1f5d6c7f57ad50ef626b32eb916501e6fbb5f9a854095d28f8f6ccdc3c8b0d56d6beabcf8578fa38fd947445c8a486a8aa17cc5012c64b21709eeddb0c4d5955fccc688a9838dedbb005b7d73fb63480b296f23282d32c01601758632ef62045e9db865bcbbd026f5e560a8b3a7784ef75b37f03d2a588b53b76de01553f78477731fc4fa2759ca49d03004a722825118a931e9e0b360b2ad76293f52cb80a0311790ceb79eb2adeb151052a4b8c220140bdb45699c12824d1416ebd2a1a18a16ea70035e69d2902873423af69e7a7385f1245bf06d1683ce862441914d77da427c210311ef8a703cc2bffdc70ff7bbf310ed56ef30ec8d9125755af03d2809557c89b32ccbbecb40110e0b786567d8531216eab5ccb8c96ddcf03a3cd7e0e5d6104239d38b8dea3131716238b2429cc6e02ce3dc8af757d852af7ce141e70a0be92ae640acc586fe960a440c4089a515a6979345d087c9a31b7f6594782eb57facf3abc51fe40d5cd0328cd90a4c840c058313b97e3c330be1273c27f4f96bcfc066a3476f7d89b5b1609718a1cb91c3580cd215dd9eaa4a95564f42d6d6909c52759b030bfe18eb47a7b9fd72e1ac05c946c372b01cfa06682b48358f48e0d76f9da3cdf60bdd53b9a09a641e12cd593b6593a62702a1fc7925447b1d7aada5c8ea884e1d2a9510bc2337728ef44d66411e112b71b2c203c1f7746f918cf4f29033293be45ad2b4a7518c3055778fbfbef015e57777be7a8f6ad535c0985e174ab4bd96cb78f322c2eaddbab2caa52c8989c1f3f03f230eec98b52ac6a0a2de8c7eb09d0e1b81834b686dd3d9ac1920ef6d817f429b3c314240487b0c527d4fe754a3e0d42d8167af4b05283437a76d164731b51894f4c3879ce88645f389dccf109bae5ece09193ea6c35de193f6c68be0827e38f4fe434a06e761b8b669b22896b9bf891f2f0a339fa0938cc231c37a223d44fc2e44ea78398f452d32be8314802971adcacfa737b2b90cf1b8fd3387d4d774c7bca754bbe8a06c6425b24a0f08152fcbbd0044063bd419f6286b26cc3104416cd3d34fb06a7494d1fec445589e56e2fd976e96912f72d377e4bbbfc482803694045ec116f4d5ce28ae3d453100f2f2ecb8057f47d41da549fedd18c27d79499ccc62a503f4b91e44ee4471d13b89a3630a4b622151ea3afe335f19ed80fff32267a32a2fef8b49e60c9437b7405a35412292b74d3c38c825da7d27efc433167ad46af0e341e8309ce6a95881de1c8a67a9373e712e95b1ef948afe624e66588060ca6a4197335e6ba537520db6869b6bb114e718519bb72ff3f913074ef5fc9cf8c115104e514b22e37a871c48aed07ff93656fc99c3f1f1beaf5ee12cd9d86a8fc6eab7cae5cdf5be07699b0e801b9b83947c6d78254da8e77b82330585ea02b42f87329a76cd09703dd0a24e01b1b63ed00926b4f4e9df2277256a06eefb77bb04de09dd8b19237d40f141304ba7de9f9ebaceba0a86b0a73310e138e02f0fa284ad4f47b2f7a4f18f0a166e24025201f5449f1bcbeab76a18832f27cc5650f9b3af19c9fbb8ede9c5561e43fa39503155c865bb9fa2d97fb64e8675cb8540e10480a85ad854ab01c94909c07a4a8dc2122acfee00450e5455b7be692db87a94ce0f367b3e6e40687e50d427116a9de98b1feb0ad0042fed0482cc695ee6abaf5eba5fb10dc46820643f4c40226197096714135716f74a10888b2cabbc27ef3d4c4a51e18eff63771b43c5833b3c7577340d9e729cf730702f2aff7ba8c0c3812028aa36a112686dafcde36d5132d4ee31203623224127df3e69372c45d7b9e0370a3efcb9577be0952af2e4c2856c0c156858a12ad1e6c54e51e4", - "priv": "370d66bf2921162f6025f1784f8ca45a58e6e72efb8006078785bc023d8cdaacb6d6fb5a7f5b3c55d1b7b4d99ff4a4e464226feda9e8c986b4e5f41a37edb84f87fbd62731259fe7266bf78c8c1622425ef797efa30ec80432808b12ac45919a2c30dfa9968d2fa70b94c03ce2fe4cb15e52a9b0afec74faa276a5a6c3913558165301232343767500140645258743061342542321447425681352486528374628548377702443573345023511515432272262636387653371116077564331128261673582164376865470573778011771888324265183248748526461364218768355482805103865333082167526282242560783314370341456383857383578161652306885528655175662755151047138555553146534343846644604080124474864542472815033627744112223432243010282717120330873340070542331872402377068660004410221333432814123760781816702355556354318770785856176381340622240247180674627437023487887142122356311528327715685414266201482028121764321760138877428245535571814667284614438305271345087160060677013335670831368663514625548365687250184502508737813417187476721462666327610566282504268562450465824881154630675748446771056374112326181781302812218455007821574286647628015822857841575474420251404400700360143301022535255431143253062813825455084682005502132778411085234725034175400186665763287222312538538408377111638782350433570758668635031106555035670557521681012082802587051366781137117633440736821514153673831736211187582851663268227614710433747764655121055850228627771006367547345372746630418234207825131867834621675040540865400710271240446255678587535712646677663862756162648235733574803251637433612543243468478708540037560522713432554677321560753633540782667588111844775721082267830084100184201347637783057758451023428802706114581247815517568146814871862414358208702618046381513554368158677108340188165884412034464317538338522232138722036733523471141710411066612126271743047838718830351623801480688837684510742872845350422860251052626017351858365885606700612771843631480036820157031348205867520520487765402767737510616772508510833486814641587451664151854305857511507587221816184780048357254801883803628823755313454274573606336453016746307562240318134330413451401315522363547183446584200387332666582654003115726104061523538637014810542557514371810386337213708847727654658851037453520630457682353101720774353267248527376013051436822206685057775611555457025261832548641805611352714453114181682076074007865877368448848734003148417023366531156644485347310062806883886101206088240403774741141888061787233830058632806617875630436082502522148484676107601474733117287574076826454801581084362107263126264670065123516671432478772264052013128365223266326033557830542056876118774244531751804203463628628086531048064586012217077568726234013258648566632205661202682265777756507302764142182572022616275154047553442287404117336235135884581014567433756542883011752430774456756024433362318460726861231472815238026480165521125855780525541506454870715826252784875538606765743657652331856072572662706465271157248031452273677063333062566472476428010820161672272014834502781064534320058730853758777214125800834724680368831480488687653825566260382261818011441503256800555554122412786818455524643670578000882636824433184045576563440255afa30abb273c678163f2e011a3ac11d88762ae6242b03e2cfbd09c41f274afed4e7b529a15cd5d36cecb76a7296fd7ebd5b56c185aec70357c401feae5f89af063ac7333ecf31be378348fe5a5022a54f3a202bc48676bb6ea1b284e85d76ea61cf1c09a97584756145d383d3495a2ef5718d2a4defc2c8f46af896b41d399bd324987cfeb50cefe71170d668ebd607969325c3c342411b647be4cd2d77653ee3f5f9c0685be270ed0299ef45e119ce37faf027ea64b0d54603c59566ca9708087a67b2d43cd438848c4a3a0485fe9f9db87522f3e552a2c91a18bfe6685d335d48fc9a633301c126d4098310b4b24e1b142377fdff5b9e55404fe682e8743a36bde3ae2df8698e8ba14ea9cb895be64d9aa061e2adf95692ae3c28e90a30f65662a33dddba2598cf925c5eb9a76d7388bb43108faa4208565d77ec00acdf271ff2a3d017cec9dc5893a655eb6e438714aa9b05aee119fbf4e18147c2d21357bb68686165ed35550862cda47a9b374b7f7aa5913a4b502dd3113a85b5a125ced5e88f384a4862a9bfcc42b74f52dd34871c27c03c90f288a43be6ab6edb01caa1e99b311330950e28893d355978fde12bcc2261cca37078d4c74abb70e46f82d5062bccc4da6176183b4dccebb601d2c8be0953754652cce06e599ddc35c3c717ba398882922333d52f70d9021c57effaafc163474707749105460b9061320cf20e7e53686b306c2963fb84dea297d2b4c4192f1497f369d52460705f25a1c9d1cf428a59020261b100a444fd057f2ca21a5401b178f3795c6d95260673eec3216a93c128e7b50a6e7c70d2fdab027d4e192fe36bc45d738cf0a08ba7922fabb19ec4a755c8b22b57c66215c6ccae9421e93719edf47929e4999538241d144c68947b5d9ce9d382f797d0c993760f0e42da8051e8c1709dcd8bca4534ebad89c67187e704e22636893e910d10c125a873224bfa48aba7d753db4677f2ab120bfa18f8f0493a396128f6426d2a4265ff5b14d0a287834cf4581f6b978c66f306688ba4fcf67fcba53ff05a6e98f7e288ddca4a1dfc43a1492f3587d450099693ecd43baa35dd7aa59513e515c1ead179c6004d9fbaf3787eed000374bdff6b72789ed74191b821b595dfaa5d359da953e26e9b572a040e4ce2172c4b73ad0fd3cc21f2b099b7dc203472bfd8dfd40c8ad841d81a1ae0a7677a666ca8be53681152e682a18eb6c804f4605630a1429a58c0293b880f455c4342eed532e240d27861d084c14d32469cbc8c62f997c24c8e43d675673c8713ce03f460de306dd194af165e021f049541793c97343b1716ca0bf9b5ae4d330985b3eaa44c60f706326208c8bfc2889351656de62f647ad6b40d6addeb7345bfbdccc14099f34a77d09dbdfd65e2d9cb09f24ef14cab57affa9c5fe48c483f63212821cd2c8c9fa1046594646881d40a66656ad9e0534e3ebdaebe1dc3fe5a6f96bf5fada52a7f730411635b3f696448a96ee1c5ed717d13978d6ee381065aa9d3c8a2e3508ba76001427adeb8e9c706e030ae2c41e64aab319c767546afc2ddb7e1e5ac0f51ef6d235c6fcf2401f9de246c80261e2469f26b8f77973f22460398daca28fb963ad5fc4715999da55fb88864e72bee8415b441521930a00c08577b609cc1240723e565b06541522075446bdfdfa6e21a45cca5297032f0db06024b59f347ba50f2787112131acc9a67f41e81a8f4562bbbde74381f3142f43759600ba69887f5e80e0488bb1de61e1169088ddbb188d2464722469c9d9339019fdf3d1421390a156b33f73e23cf9c2e1e8139cdc12172433d7e5b62ab55a88e34be956cc62ac6e469c4daddc4a3befa5b3d7ef2b061c541a6c8eccf2137cfd0ef24d0052646492014bf6a604bd3b8e3491497ebc008c68033a48eb54673dd28abf05137c408ec9051853bcdc392f6aec82f8ec5cf285b7f8eb7eda1dd96edf0b264880232ef5f659eabb78ed48de3bf7fb439d3b1bc92dcdc1f53ede8957c8fb244483fef72ca1f18f458cc5f1b8a15da992ae5e69c364b59d69e2bdf82b25dd56af4e34546dd732882e83530952aa7add397bb69fb4a5091de23e60ee3f2fabd5d81370ad1a16dce0d4660a5488925bbde4e7f3c989026d8788659eaa0ceaaa8ec16261f255df7298906d9418b92dbcb4d1471a4bc7c6842321794e3ccf1dd5eb2e3d13a47e5489223bc1a9630ae2b881a160650cbc38e7198494a58ff65f2099b81b44251deb1d4da99ec3658366fdcf918919741a4c2a0a91844f4b97f3c135392a9e0d41ae6c189d0d93d4e0f6826d142d2160b9cfe60b7eeb0aa148bbbaa4da7669c72990f8beafbc6aba9ab11d3083e2c337d3ba6778bf7009f444c122aef14f6c8c1d800619d22045c88e80fe1e80c505febb6670a79802e85e96cbc73e15982da42bf530fa5500dd321d8bf5eea7e02b578a16c099ecfb47acdcba485436ff5d13009f51e53be19f457187ce214c7e4d1c4ba0ac68cb54d3471f5b1ca714b5ed52baa5ef9fe75e9758d1c92be75b821692beb24b8025d2bcc2d54f46ce8f0ef4bd81d35bbee670592184f63c6d87e458f442718c7d5e85be6f0c1eb0d9ea0238a33040d4d8cb0cb0dea36931d1d932840893743aa426df8b9222e80338c15883df42de0aa6b837a9bb7ed65f570ecd05dde4294a4ad23d39588b218acf34419f3fa581e22b4879093e4b35dd2ed116690a96af422f10c511c49393fa25b61fad39a14aa33564eacc82c8f65a5d0227657118527d66f942cbece1c776e252644b8a97e5a564038e3670c31f3bfe93366bceb27648a904152fc907e6be8b6a91103cd55c8000bebb60545276d595cc738b4a2b1f9e30693fe9d6796dcee7709fd2458a38856e579347c560f8de440f2888f38fee3c905be51303807f2957932f96a3ade5ca77e5616a44b510b9686500cd8e97950afa67680e236a0b5258a13dbf0e096ecd086c74fb5476e2ec7ba929defe11dc8f4bfa2dbf21158ef72abcf0675b29709ab9fcbd2755633bd274aa3d5426eef9b1f712308e7cad98ccf4704f1d49cf5e189ffe80b4e17f950a1a4d14fb6cb6b0c0d910bd527f35498a1379c9d034a15ae852bd20395d4302358b3e09ed64724432ace05df83c3573d71bc5c168c4ce160ed2b7a79684ae20662651f988aadae591159a1400ff9b91e13279764ce8c14f293a0346fbd8ec833bb9d6a4da4260dc221401a4af80cd8b71420551ba188ad8de6d9723f49433a7afb855747530246a4d1128b28a85a6f16b7584d4aed3809f9a2bc0064b5237823fcd1eddc92c5f24a168ad3cecda772d8a9740ffa20ff91612b1e13f905b2a81ec4a2c69d088df89f2f20e59523667109f3664056bda4a5d70718302e509da989106b1ad7370c4a9527aa79d2bf8226ed487fb44a5b872de95581e491b241667c01c4af5b639ba1b496a2191a23de453c15f9eee2ebfc4fcc3d6098e31c9c33bf8908d4a21cbd14302e0f0aea458df776d75e929487a623a2fec1" - }, - { - "seed": "03d86b249cf84472e3b78b12110e2c09c7428fab65d362760d0800914696d411", - "pub": "8848322a566ca6f4aeb022cc41ace242f84afd48ec429ff2a107fdc381dbb63ad301f719fe8e5784bbc4f7952b43182748481ef5f9ac848d277c819e86827de234ce3d1d90cbcbef2725971cf3a559ca903896566ed66e4b452a1080b7e825179882563cd73aab0fe07452dccafc27fbde1a94d750e27c2a67f1b47397c50bf0b53e1c2cdc2dc13b333e9be0399f271287e4c9ba16fa122c418b7ac8dbd5769ce792a66475acb94cc55d70bd7cd91a62fac1e59139ee46072a7f76766ae4a1ac3c52a0c689ecc001849f5f6ce436b29fb5552fa5f3bdbd662a85ef86228eff2ee4c9b0cc0fe78f8da5a70231d6594430a70c878df82af33f1ec8c979fcc8777e00e77c457300461cb93e9d33aca87102f0b217d36556d9ba2c2a23a736628357831128b5ba6b649109972b42b15c563b51cadede4cf3d9fde08b456f7a9f2ef28f3a7f18d5f3cf4bbb6bdccc98f801391d78ff0511a09dc07cca1a81e63b08c0eb738e1f942387946d3b3bc7a0f658ae2ff83310988bfd4adee4129c68dd665d12211211c2d9582f80ac92ce3f943b61c6c45b935d38b27d3c1c2ed6dda42fe43d5df6e5f6bbbda654c35dc259114d288c9359fd41ae8c2233af33d991bd283310bfc261ca0c45288dacf1319a70e93a221eca835a6cb1fea3ef0cd1837c0c20c51c3c8a6e81a2fa638355ee80b61354f50a061ef5dc9e3f3d41b37bb08cd9bdbfe42a0bb909bc24edc022ca57fdfa2ac70abbfa851e2a2fc73e72e06dbd0a73ccaa91f399c72879dfb993f17408c9d8e5b60a6e74c61dde19893512e63db8cb69af370a8d0a91eb39334900ebaa892bc6dae48d97073553b4a479475ec1afa797345c6743bd395d95a16b2e8d494bfb306b83d67222b09ca917334406ee4a021d318f364405d74ac23859899b6c758762369a63ea6ec3c9236fc91578c6601ed2ed93f0873026e792c010e187c54fa1cfc58bf88939d295539566dc50600b4182d5013c262889aa964fd15ecc00dcfdf57b2f7513a623a405e31811481937fa6d4deadd7402cf84d050e4fea37f5b86dfae2370b1bfc8b9e6dfab3859a6ad8712558e782e5d5c41206a007d19d20071e925ee25e8f10a9f04b09f03a4e1aa017a7779cb13ac5d67ad0e45f32c216f60897de2b77b2741920ea73da07ada1cb1e3ab5c7ff0841c8b4d3b369dbcd7e5e705db112d0bbaa7549aba02ad762460bf2a80d39918b99b5a0d8cf7bec174c94490c3fa100c19595786ab729c05e0e02538983a145e4de6cc10936cdf2adf465401a15492a9c0834d5a61f41099bdd7e92e27cae2377d44f61e52c5fcc46f58981a1feba332b1f19118362ef2d12d12ce80bf017a1ae2753c20a9ae0e8bf4ecc5568d741bc64c3f783cd1397400ddb3da525a3338f1a725ea5759a4a2b0b4d3b0895ee07d534154fa16d77a3aa3b205a8cf06274957c4190d47fb9108ebde24ed0cd544086c3ecabcec0debfbc368c0ab67d065ecee9cd671784dcb4dd769a944e44d9b951ab3f4a890c215c1b9c9b962687a576a0bb15357cb5f250edbaf7ad5edc3fcda793425ad3516aab5ad9a01f5eb036c1b6df02ef51516bba767e1071178ce25d8591bcb5276d59233f91edef0e217f39aeeb605f6422ea5d0f47ca2034c4ad449c87db3c42a5f2dee9f111455ddd988a7eb4c285711af467cf8be4832deec585f2cdf7f68dcb3cd25339451283e618a6a3fd8095db07b8f5b5df79e8055cc8ec3c2b55e0b23e18caa12a991086c7c6b87a0713b4268a72a9c3a2db6b07514c6b7eb0449f20b096f88a754638e55e9abad72343c92dca03fd2c4df16bb2cbb1963c8b9f48704caeaa22359468ba67d58ff29e38d783999218888650d6b414a41417d239e6fdff8e382f107bf4feb81744e074a51531c38b6dacee427547e17bfd2c2e4f4596071caab4ecb31ce7769f5edba651f6cc4380a8a1711e3bb12a3d8a061a11f669246713d29442f0ad39629722abc838ccb51bf80e9c440c2e2ec88d93076253f56c61816fb725739b4e44427fa7ecbb415b6e5675b6aaf736d592c28308ce432d117f388536c83f90ca8fb66f1dd543afd147289da0c8dba45fbec3499db3ee000b26b49b0feee4044f231d5aa9c71405fbd754bb43659e3b59980ffaa3e0d78b8e067cda206d7809d76650e4672ef4db8c74e6244e82efa9ac02502e3734fc188f434d3acd65cb7f9b988b1d69b1fffb69d88ef2eb1f2b70a2d165b0ec78cae92447ee5376b0ac4363b98689076123f2de26de1928ed2c4182c3180056694cd6c8949a85ff3b1e24ef12614151efc76d8652f04017ace8e91d57d059d826cffb93f3ee6a0405d9a4cda1bac97d906a14537f3f4e62df70739b94442884c0c0694b438083b5009646bfd58b73fdea8e9c97b18acbc3693c07cb6c750353f8e8b704b2d01346619adac4a9b05fa4a478c7b8f2f6fcdcd6f9766e059e9545bc566e2acf6961b29ba91be7c425b1efccfd2f8abb9e3b9fefba2a4371f8f9bb20448e9f2bdc6b5b0dd4cbbf04b30a6f819fa271635fa5ccb6f5fc1c3a70e40e31e2fa23a640aac6b4c56bc07b948710e66284e483a2ac418313126d8e79ce9d31a2b657bc5e5d7260019e101f04ccd200b29dfec7cf888cce69c11e70115e36e62d94bfebf99c2b37427ae66e576a9a7d66ce0bacdab0836343ffe0c5ad719e503a07952faa8a08ba3380aad12c1b16918719b8035109b932c17129b881015f976cb27854279888bb5a7", - "priv": "8848322a566ca6f4aeb022cc41ace242f84afd48ec429ff2a107fdc381dbb63a8b9205612461e15a894899f582b63ce137e1a2f6449844c6e1ab07ffa975af9257eef1899b521dc105390dbe918f8858644d8b4be502f657606ab402e005a1e646fab4cce2a201faca5d3f8073585d77e8daeebbf03327be684da62f446fb8bf11333781374634823864042432083342054315306250442250826183726662656836707207736660161824455431866318670240311553240312347115152581385651705245784026155414134588730150508327407213452331305655400268516817024258565182057835868833071380163376245221257278005855363453284531033783707576026861505718742866514771740874438446244726810142022470677257603785402032470565871511738035371647503025642426405205382454702086852403683351111368612567430634780474174484634822170721682005744765345483340267364815826771864626134365402244150866005531353283300630053128674405643208648637486012828554178631542254248251856301082170407214768471150867840383624825684364366438030362238282104043061255215621210686101367563532532562306760522550345502415700162084747110886865313326700027831108836087336210727177214467302222658180777371060148146602645888401352857182336671315855802221313438166008560261203061705863553051286285235608241467031187205708420581371001823637854571517586144832155022232600160485088873722360483602837746658646860177715055875558150641212362263864175584814328466146518265263274857302328063567642227558860841183338043285138556553222668166416277534867861727330746664576480024537803586435081208274002737517430415402722305805887888006778232512782523462685012826525455106007263311385032752711256051815357843176702263215670485563168666680358667680544184345338385515177482431554648487165220470888673712742761144130066376423527701312468340042581563652578411642814866606020050483618642353848611076208376042661087664224038705704184504657206570044150271443252440031002705772661801304248550017226385876682044215363807531016374814725644264133280774048845453460315230256666151016313714182805604006003275203431342570007274782878487383272346602306120123182336428852143161760614620647282877803338426417217267534810317714120637715587447884238722162264175700647268123018833033454700328881216065721525378787614880383841413262040530202264523768288244748401630013064582441506825281343376027562685201588256074212735338587526201851804705483838426483651360202665338765886456254245744670566111870525780254234553032810841267361136718675661103883076155035127073645528165635100567720655217755421301357108034726505744587147310040141010805646522087147007255714057158741217277422625282364731745870783664616160434555775443743502840544863386473378018153247320635606807438754156737641371466713704031817403002217663388070881274501471075834867805472376776326800354057684821603313825840027201144475741126230724105836354806407505613633022136647710632508145086447881758420157178754808160145254472146725788070481561266847405464138405113446032102601304210208730306401431145205104734535487474140772264560342348655301266821517162211403658702262776371234537788132058858823145524452147323040308527184140733703820531813674657553835474053654050304073176263545064447138716350737634b643a171f66cdf58ddc280697c53b4e42a4beaa9754e6be2ba3a38995d758b1139fd3553664e16c952baf99035d4e2d089e48d5ad9cc29e4d2b41b6a413d7807f5321f52b06c51480f368b2eda86074aeb9e30427be5cf548fe5042aa154dd0dee531e37aaf546bdbaed6f7bf1226fd5395449897e9935770991b81d23c884dfb0834b1493781662514c3f1d666185ed811847cf1c0042eaa330f42139c94928bcfd81914e52f29bf32e9ef9276b381d6d17fb6e487cf8cafc1fa8988394161595df71d66d504b4aa20b17ec08848d59bc328eddd2ce0b618790cbc344ae2721da47092a438ab33b41a490475323593968858b61ef2c0e9fea7d67243ae69ea6561ed8f586c3ef625b0e560a7f908ac491f6f76d68e73db4718346f5a3dce4c3bdec93c1ce41c1a86de45afdf43e73b5a3226367db267c39d75d80f831033c0932e537a8a8b27b1c82190990b9a949af6a2b9cf6595d35862be8bfd084c117494b56cb00c671aa902a6a7179577c0b9c4d615f7e1e2058820a12b131bcb96be297f14407fcc7f99aea65f1e4f2557f6b946a55754b594c1de5758d76b541b568fdac78f3c6abc68edfff0be8ccd2df86e536f1ecfeff0160459ee05f55be0bf6cccef37df0aa22a2c01a28a0fbafc4abc22a07a2b60907c6523e891f18c264eb0a0589762622f664b7b6b65d9ada3de8b1d3a417f88b9a821ce7d5d321fa2a64d4b2017cba63fd177d5a866d537ba28e1d0a22da42b471a5d4ca50c9ccf42494fa002a35d4b9b3931db7b4d30d1c6faf0fdf7f3980a20d1d5861207fe143222415fdb586a410fed5b40ddd57b5208b804261880e25de41a4880a19f7f6d49589ce530961fe2e28827621f561515133dc1fb9e2bb61dd7183ef2cbe906e292c0c7d61e04a0d61623c897258f4bbd645b30d2db836c75481aa3313c12660f8dc1acc7ee159d6799b587c85992bbbd1a7794068d7980be486426156a19b9096ea4abf36e4e8b524d474ca60ae27b9dff771c64f0ab2844372e6daa50df760e5a56f6a0bdfdaf7224b48692cfc811ace083f19cecfbb9a72c309cab467df8b79d2f34860c7c056e8c55514a53975d407b4000119eef0d0c8eb05524ef006886764580f697c849b8b2d2e4e1db15992ee072bf4b5252aa1542ed4cc9e714c0ee6a447b838d233355228bf4e427790d8a46132c50d3e340018a9a3999ce187777db336faed69d7259af20e104e9d13f4f89afe3d60e449c8075001365ea6a5b150706b94828106776831d8335078f1d590f6eabfe3a01c351da0c8aabf324aec14bfb0729af86eeb4c646d293c3f5f3520554540451573a93bb05bb3d70771240652751356a52429a866aec7396bba9d71aa078221902dc1abff960da9583c58d4806d65d509be5743c9d42ac7c8f7611226368a49d60f8e24de73fc614eef55d705dbfec254b6579e207322426687e3b1c5c0a05a869cafdde8c4f06e799010db17fde4815008e9ddbf7dd9a3c63ed11866dcc739c6c97b2ec58b94900657f3d881bb9761d8f64469c68a5791311ecf13ac0d22877d4d2e6629e5c4d4640ddc30ce904c5faca5356c72fac8abfc421e18642a1a7cea716d9a4a93e115d749e16c79f29cf637a5a6a17577da4fa5184fe7af22a88203b77818b24fb77715dc2b44a59fc2b4ebb58289bc308f8c0b8718c8e40a87a6e6b5133ccfd2d846ac98e02ef3b210fd2e6e1ce8306bcccb4bd9c345f4be59e931b8a30e3f9f82549c0084f72cb13d6c645fbe61c81319bf98474b386b7799d561e53771aed22ae04fa425d3f61027fd710d897cc4e6894973146a6fb2e485ea3c127ec6794554b4282f399de9897e1c70f2886d4a3f487220b00e85572a4e291b99691aef60e10d4dc1515d3259f8e74144087d4c5ec5b0cca2812c27e3df2746c1a015644fc5b21008227b29328109922dc95128e9b646ecb9468374594c748de019c492bb0b6444743abd20a08efaf84892b578fcd389dfe25f0f6bc20aa8993759ac87a0920d7a43b34cc43cd7fca8a2ce25bc8fa3d246869e3d965d98cef0f3fc39a5a62239d803b7e311bcfcb9d9c6c484516ac3e65038daa2806d4d0d4073ea623a60f7f68b66c97511c1e15ad5f72adbab64f772c4a3f4e161e0be0386d7efc60d497f664400df69924028764a92a26959f3fcaa30923d3f3d219c91f0831a1f6f02b24931d57d5ca427d8e2c02d4e4e6d4ea3efec061cfc72941deddcf09fee339e3a208e286d9e0b8e4f9cb900d9f36c013adc673db1f69d6ce170197fbe60ee4e28e9dc66bd1423e80b78a10bd0119bd59c1c2d4eee1cdbf028bd9d0c459ca885d83ed2ba145cf9ca5917f6f276b4dd4c9dd4e1a0d4545d2c66492b75a42da066be5d5b40a28f023f49ac263a45fb430dde7c55cb78882bd689de65c36af223925eb14f26cffb6cd082cf6aeda6371de32c5276d3070f89ec7342e94ada62dfc11ba4a0b05fb6537f36bbb02630643332f121c93089f26de6eaa4886e4c1bbe25e2d0660a1db2582a6f586c1ef875a406143194e2783ba9bcba4be28e643887d14a13652cb8ecdbe9e7da4a73d05c926486ac2518dec9c82409f20679ef33e48aa0a44ba2fa9fa2b26a8922d5eb846c96b32392c46ab9f7930ed7a0b0d121ff874dddc303dfc57d278760180b9692579bbe0a079b8ad5a41fafef9a8db95bec8c5bb0512479d2e810096c729aee88741f85a308aba9d5d1aee42564c1ea76d41ba78ac1b05d5c604d3860ef722d0ebd73ff6dc894f54fdb8e4205bcfd05d199544bfe6ac3136db83fe2794c5376bdfb6eb1c886a03cb2939f31761b0ef1ed877ff28e5c9f2fbcf7d1dc24079b4790825410f3319c76425cb9e8c385dcc2917ab8a9a743b8bcaed7dca410563565b553a4d89ec927dca4a4b8c1085eeec5c53f5d43f99c1737587276012e5de24c8c012600907737c487c472117bd48f726ca8d4e876ae35de494e63d0d844c53cee75af13111251e338d057d5a88dc3132126f597deec69c149220cacb942b07746200cc72758412faf7a22c0f73389615bd5fb87590c4f42bb451e48a21bbaaaeb12b427748f4fb02382d105fa962b180d1901307b1f03db38c8a0ad97a8cf615c0a9c18fa3a6c10e1b7e0a83777a9ba648d25b0051be791a05bd7ccf713942f17eee24042b0ff47aaaec674d0c9876bcd3ac11580db1245691dbd8dfe791ad40a1860f485933c477adafc3edd030624db77da7e01e7f81417e394b3629c687a464deecb42c1abe5ef245a717fda612a85663cd9684a58b3124cebd1cc5cba3a2a8a48b168fac6760375b8a62ba4cd7bb4f177cec05adfc9ce35908d78debe63e3baf803f2a0079528bb4b2f782128c0ad576092140c94a980045f998d89350278bb6867806228f8b0a8617a6caaf54ed3c70337963b986c68eebde477790bd316e572d823d2032d065891ef8560bacd14f910d3279501f97342a6120ec2fd8a4f130df18c0880304697662f66877bd07ad2e79acb4cfe4f039" - }, - { - "seed": "b9446e8f78c8b7b2acd335b10f0b8fe1b34007a1d827eb5517710569e060afc7", - "pub": "940f3a043905cd31a66a0b5e776022c026b8cc8c9df839951ec3038aceeef9f203eaefc937d6d289cddfbe4d5b104abae3bd76989357408c69922bf39217134df5c806d34574a1ab61acc99a82f51852f173e0bd61e50552cbf5a8aacf06588470f649adc715e3c7cbc646e168b4bf0468043679aa7363144cd6f751578be3ee5f74c96107189ed1759929dc3107c1ca5f14fd14f3cb31503ff08c8e79875fd529ae80a1421c0643defaa35d6889fa5b6e018ecac896447ba6f5095929b4a5cb636b4c9e0875d5b02de68ce6dd54b24156952e081adf436f064795c4d099a9c17f5cefe19b8ee8406f1bf40aec03a15d243f870e2fa2b0aa54edff17d2189d240725354c2a680f3e3f7f937d2190a2076b6437f5dd6983699f2f87cfe04aeebb22a88132611fe673eae978f01bbe3959aa3f4e9891ee9cf6d6031436c8caf9faaac52e037bb69ba454c6d1a7f1472d85c66f978a2784c79e792d1b8b0155d85a7fe1f9b049f012690a2362a82f4cd9e913dcb0ebd67d68595b0d17d085af96bc64f84e069c9cb9572a7864ca1dcad25ae60f37889d416a8867d4debc7d1af997ad04eeeab9beeb027aded41d0ed3b46fdda94584c0f787802b7a9192d8ab1547a15bbda48e7ec65af00152e4a385f755d6c156b4a5443a145f84268a55437ede5a732cd7c3b2a6a728ec698e975758a1b65906307991ad8cedcaf9eca859de2a7635efae365647b4aed61b28c24bf4662f7fea3f14b8e373e4f3e4ed51fedd1d39a2b70460be3e7d213fc51357c80e292b9649aaf7b464332fab8595bc1f87baf2056574ac9c73168e13db1fbfbf29820efb08e5cc9465bf31431a96c91364cdef8a7a53ac440fc40bd990f327db60e980499b7314cf5a63d95fe20baf80d001be16ade597188cab8cd217877521e9815f274d8fedfbf8ae11d36bc42b8f1d2f1c7f4397ff4087b73e00aaf4e9fda6f9499aa469220b153dab01512abcc6f5dac0c54356ed2ed0a1a260f3f8ba1f67d047ccd333a26c5137ba76df6a45bdd731366a04bca2f80f7b011baef941e91835ee218af34357f47a48c6d5b47dcc282bc53b1465d5775faf773807634a647701bdaf3455e1536fe96cec471a090d5fa7b737afb670cb0e2cdb5efdf5757cb52669ae1907d991a187e87f19dd5f2751cae3205fdf832b312fb44225b7d9285328011b5e081cd0261e255b4c74a1aa551305cec1703cfc5ca1e55a3d1e4002410a5935dea3b3f33ea0b9e17793ce6d171e70d954634ddc50d6b06a499f25ac5959f282e12d8b9c28a00c58371a56a4500b2c507f57bfe85fde137f82929fb9b813b205f72feaf23b9457b746e8c70eba61c80772fa8dcc94afc0aeb59426043cbfdd6cf69f97da634d884beeead96f24963e9dccc71fead90938956140ae0c486ad185fed8266c515037a1fdcfa2e211fe52e0e45436215f123d8137de4a679b19922c9a6c1860bb7430d0950beeb635c0937edfc5966d1aeb418c2e52ac41d134b43cb9a4a3305c4c669892f65978006fb56ee2f8a7566f2841ba1feccbabdc49bb92ba7e06842f6c7b24427923802eabdf84caf5b3e77da7f1207f8b0497d17ec1b5e3527af0539c64277918eaf8fba7457833ca80ae2a8e001ca9bf08dbdbdc19cdf82f4230b494b07594b8ab32710e794605f93adb877fcba8b4bd3a89d907a92f1fa309727754a42ee1da7ebacfce46d07181d4b7f7d20028646ab680cf108bfc3a43834bf955483866759c7a34105b4a34f92df2190be8e5272d0daf80e8c5dfe361b66d75a7d8783db9bdb92deab2bc703d13950ec2acfa686f97ac0e04b1e69e5df49e54aafe615a493e96bfbcb008385116feed54a2b984930886a514521efece22f449ebd0f18bfed1970a86e7f4d96eafd11f135a9bd8320a12aef389bba46b0defc101c3a90a99f00e6d5cb28298bc35ddb62a1629374353eaa79830ba5b051dba82feb251444b3044b432e675792dcc8e464bc40958c2bab862208486647aa879b8ad7a71f48d63c3bd0b38bad9edfffd1a28fc3221f67b26a2a36a40bdeb3d01e0f4ad90b26c5cc9ad0d80e24d5d354d5aacafae1000ad21e4f60d994891621b19214f92657006e01eb4b28b94f804a7bad9a120226cc03cd634731ccd5d7610218ff40735f7964c6e2e4c119a590786e693820dd75f6bdd58cd6a1b8857645c3c23b52c96694462832ecbfd27ffeeec6284c4c27b1fd95b7252857bfaaf2e5c34f51a4055da5c9a2c8e941fdeafabf87074713ddfd9443aab31270cee2801588e7b89f3329f3b9e9f398738fb0eb0f50e337be42000b5876e84f623c258c4bad7d1e536528e8bef4ac6f6869ae9738ad76bcf8fdddbee023a5a836020de542cd56877dc97cd33586a637fc6c1406ed18333a32995e14d79deff1e258b7fbe76461680c9f5d7cd79165944ea50c29087f46ac6392c1cb8c3ff9da336d4787e81c3662c384a603ec6bde0089a5d48136d08dfac460acaa0bfb0770d85ed2f859cf3d2f1e4c82d5c5e8d6f9bd5f1538e21fa15ed28407aecd7e78633734118cc4c5eeec2e2d01fe75e1b7d9bd0d149b13b57ff5246655ed2259544bec5d06639bf6180bb8daadcb49ecf1c0732d530d0817337c4fdeec4dbb99f0df41accfa48eca5c5b8e48cec321c8a1187b3e2018211cafa625209296d77f6ef6f14da8388feb69c11a912619f514dd8bcd5cf0ac64e7ff3c97fdf06b6620d18a0f95ffff5da533bfb61ded91be2df2b", - "priv": "940f3a043905cd31a66a0b5e776022c026b8cc8c9df839951ec3038aceeef9f24a60eca34fc68fc31f37093dd96aa4b9f3d5830c6f16e5218b03461992816f1e6c46ed2183ec938f9bace6d938995ab55b79d7718e0a65ed1ce086775cc7ec0b9d8ed16ca18d454dfd93287074f1753cf1a106d43832069924e934b69a056d6d176426004013076575326430863137681154388472321482327058660264144318587126616777245665846085207077377620134715340864342265500652186150467601565650873175644064416834227733720173774587668873453654245237887584735816803431317252007518455862453438544280565558788488641766433715102273116838853016286781356764553350815576130623142120288320447330858634146116010314662770062074375774867186530144058337264066324211032656066333521814241564325222500443323140011323440703778825861335111403817102184704327185386633608142215442067221665320752283741503126550045540138523388552553756710758782221066048054785368634370510608715285855830261461583231884206487168348502251624181358250452363431358088283280220684850274887682136732878487628835676427436605335002250861670280661746364663333746081501851137351028871688754020075563164387882072231828620163852404354634175131783368268806428070410450722647813676878073455762434565702154475408122163541077486410856021580604143745384424577785383320062585216722084220844048307024134432474888345716725321201005120225816884018256740445853733442120313688418144003171551700522688612013631552624366072347843226703122460417203012430812021833811420720661868774436374256462732481621436813002757624755522350808162680011825038722214273025248005052317717234810061288158327831563165021287226153061841412807135642600053623232871172234266585054154037728672161210616458710643372418828532614851034330455673523587742236477452251870078026584337870552270745526756623860278447626062284834315340427146171232766872568061730756050724247027148476041120506552842756071205358731326167423273744026237525138835086634357501537604145556133481414804060470432652463216123837200443812665470481367442016456162841127017802443686606775850025538847122687372785518286573566563606242666874533554403325385363656115174748320261462840552772623674410481265030724763256241631486648346756261368748180167401048541280737780881841151540185080052416176233736633170701131856087368601514425225057047273141367358256783768616620301431740016335013544305727222457250283187257250743134642552508353067725664027065305156731547334833675272822335860257083672157731427677103643242465216121111244014577786563871520155270585467046042052457113044834347701052060663740758787647888206363867766446811488063441365214110100556377588423480631304107844013871142521788152386654530207028734623080264311677371668465072078164640706288825415386285222822305247408773601071322560410302142821481811133677651772473201332288815205035613301832085104746827523346476715450002575314316042733172642714440446820038280042757635636678707806871714311068015364432431546245667366443671858840683530203154356038363103684425222575835848370481228786854711047404557132636566284507601070068815183715138065502835833765443038333301854266005471082640210720634670243202468375243858240881712734844607240223ee143a505c81ae49370e4b4215ecc3a31b3d08ab2504aaad76952654536312f6b2298a20a48791a9236b32bb68004ce49f169a4a91c189fa677ad10a25604a4bcaa38baa0e572421a79cb1f82e3543a285c5bc6bf25eab82287027c386d543242119c74576c1126e284dcf1e25717306223cd0aa9f6ad025842709572d1a1a2d656ae4388b6f3f491a0ea231798a70a3a0fe3a7f0c97e74251068d009cd0088b8b9026ec8fb19f181f0838bc4fb5c7196127d97d91108d5c7ae2893c85c32023175dc204d0c000261b382fa078dbb3f0745902a445fd5a32a7cd12ad7ab014f5df7b9d504fda8eb8a00dfe5dd832348fdf7a6298af21a8d9730dde60964ec8fa10b3140d409278c238a78debeac947e740547530af8a98c24e6a2474f1bee79e762d710ce68adf282fc8110fc099041b5a0cfc307176fb9fa214c3d42a7f2bbbbb27fede0eb37c71d84811dc34c83ace1a41d078b936205cf5b726230109a099b75abf9152824e04c352a9085bed558c7c894d886dafb46c3bbcfc2a74ab8b4407e514767d90692f94862b2f7100fe76cb36f52c3bb2c7920a76f642799c213b80a6561a6980d611d2887a0531cbb412dea4be23d41f515bb8ae38c77d93bd603f9ae2e55b5f0dc6f4b2e217c98f6f2f03f9952f43be49e6a7ef8129a265eb342af271d2b3ceabc86729e962200faae9eaa62d04c64ed91e0b3d8f8300a7c24719a9f64aa35804d2b5faf7f3f617963bb8199b2b842ff5317d43f32b04052ce5f3b7df5de8e2fccd0b183fa767a3779307d8dc95acd2e36f4a99945e12c0098b2ffbaab97b08aaaf9b30d2531906506eb5194564c74468385a83d0d4291efbdbcee7a3e781dbb81c3f876957dc169c19e376d76f7e4aa0663fb3e332410aceccb0457e076f25cbb2436a89d5bf25c376392e719b2b49ad2ef20fe5f51595217239e0e3c7d40ba0ea3f3bdaafe29e283b9a2b93bbef4977e2574082e8bea041de33244dc52d71376fd051bb790dd94899c80466c2216879166fa46766b7d23899916fb8100abf1a1adef0fdbe68de44774e13e1104432503c0ccf39be4444e3564a4740a101dd654f76ddeb32c510077186709684ef6ea61b325b8fab6e039c95d6c19bf09cbcf7f6014e1fe85920aaf974c164d8079e3ca16707bcd5da704f0a66a48eab2853225a795deb51d45632ab38a07f093308545a7ee29fc0309b48a177dcade869484814652b70073ad0cbda32d2965e26e2bd2ae66fbd91fc11e9b5d71969953981d020ab89ef3cfc3d902ce078abf948260035f9583c34f1650e647992a7fc4b3814ebc58723349901171efc1629c0c2ddd338891c48a19810779c2941acbef58361b3a84dfa71d80373da5358990b65922e17ed7066e4153cb637fb56605684a94284a907c92a2d717243b731fa6f3895e8be09b7ea23a023c6692e8f2db4872213eba4b402d764d2dca50a3f2ad278f33493e9ab83777f971476a1cbe9f7a448e3e9d9e47d55d8a7f04b1a380ace616ddef3625efdba9a625b19715d38eaa295185b7199d81700a9ba454a07c912187bc269c7bd8d499e14557bf206a33381996038e27a28d19ea9672574b017799a27582421cab69b6f187cde5af2526266ec10ebac90e4554143aba9fa448abb8cbd380903eb2249e124f2fbd230e6a91342972b3c01f81d7993a5a1bd25c4e0f564cd4597a18e828f536ccedbf66dc85f343949b1dc2a50d58ffeb67949e596af43e1e00e13c3bfa84fec72e364e88509b8f95e0e9c0341f3a3da99c947be21da56de9acf630ddbb190cca9312142640556962599a52ffae981e3fb372c0a2b99ef2cb3b86ca9af186939cf277f32d503a5e6554ecd0259c52b348a7e107de4ecfaa35d86a62f98aa403f911491c1b393f4ce1333d517a731e106e191c66c7acfc13edac66e9e2c5c3aa261fffc6ce688bd711bc748376e25286923e55322e6483d96dab4765ae5d91dfb477ef5a5b61fbf78f248a92d03b18a7fc247615405701c08e5147700f41a35cabe1d1a592582a2bf2067653d7c925146776c0bfc84a4ead67619c0196a0293b94ab5fc30900c25d341e819f443c2bfc9cf7d4c3960c6c7e6c33f656b3b512752a55fee1db2b4fd799df192feb8b775e141a0b263a24710aa98fd860c18d490c55d9a44a92e1ed5fb9bca06562f2d1611e35559c2dfee0ae1ddb8d724a36cd16cf728b2652c92cd8619b96ae1ef21b2d2c692cf02f9bb43fa0e4c87e001a3d6f1b7177eb43028f88fc024005fb095958bb35dba11e72d800a971b1fec05548bdeefa046947449209964328c1b95607aaba6dccebaa3b9a4a175760f65990e36f0299604545311179b3a0fa7a3695053ea99b5164a22e1da59da3964d76dbf5d46193055cfe1408ba943b86c0b7cdd2ce95eeffa95eed74ea018d42d891d7ecbe5c8daa52c04510253f8ccbeff351274cda464f51d4762b68e36c783041063128878d9820aadabb2bec4ffdeaf61685d9c0fd2ca6626f8e3ba66678bbb3b46ed7fd3a9b4ebf623e37d90bb6fbba31c9823e8d7379ee6a42c4af6c15d183666195f509f3a23d14ecc4faa4a35b55d122d4f0bad9e0db8dca918cb2d13e96b5e2eb2aaeea1788614bedeb39691b072a094ee22a6dfee43ba77a46a9f341c9a95640c26e7596cb6f0d0889f75789fc54e31fede42be11d09f6ec514bb5570568d395751ce5d4764ac64f4709c919967aa7e04feb19cabf739e1b240cfcb302321e3d012a2231d0dc0d1038f84bed48ed94bc06f65a3f437c9d8fb2961e49b292698618f55d06360c8661ddcb990c68d1f47be15640bf059b7d7ec8317548e20c83961418c38b4eb278c9d86671af17d2a2e22a2be605fce1e496b5b1dc08a0d4e7b956ca5a28116cf83fce69190b1559da0c19a40abf85d5030e0e979c3b8e174b42d0f2709e28ea9579332e47045733c15a63dd2026c6540654c5b481df921b2c4fa9729b817a3282aeb9568a6af7de57d73abf0a04347a96263c97b575eda6e1e17b2caf8b1374fef9be11042813b4d64dbed1dce9d452cc0e17f67d51022b8af47d32494188868933bf44b956b9660a9103e2ac233f907cdf2adca9ca51318148b325bd29aa508d9a6f121cfd6bf37835f9ef9e3d9523f53be11687a2f19da1580bb868038a1cb0119585ad8a2aedf39c8b3b7130fc5fb02eee22279ec7ed7192b4fb87fe60cd64700cd4cffdc4adc518c216db78c77d8e78e2a8509636b9790af99616bfc5cf3394ee1e044f4da0e22d50495b887c6b2a07102828e8ca08323b3071972286022ab78a794e3ce3a31897a2dd60d26c952f51af92dfed277fb671cdeda5667887cdcfce78103037742274a82dc620b37df769eb2332d95e3ad6e2b38eda6e9530fa7803bf52a32a1907a880e18e7b5cf7fa751751d24a59ced3c08cf90305fd55f19c6c902ba7af6f02464c1f84a67fd85f81183866c544f080425fec22cb6304296e00f41b69f2addb5ae7f286d39edf19dfb02161bd6d5af66d2d" - }, - { - "seed": "910e96cae3f7df10e0686dcad2d6cf8e0dd9ed69f3661f0799df91cd6c494986", - "pub": "ea95d53403e54cac9521c5635e9f335f75da4ca76005562e75f666ba598df28db7effe2546eab9785d75da10f4fabf8bc5a3ba57b8510ad8825e296f6d1acbd0350b05dfb4e58a120b6d001dd51732740bffe855adf7b48ae537bb790dee364a702310323ebe2883609d8219e85ac252ee56ff58c5d6579323ebef4d3ea265d1e65b446af2436c3164b0b984df75b63dad2d3cecc1f41bb23560ed67842cb76723dff07717dd3d9516580f94514b1fb3450d88f507f1bf07a3766a6e52c93f972f052ba165bc8d7a06a7c96a0fef43ebca6fe4bbb0d236832b70dd54f4bcfd007a09d4e1024817ec0aa397e9a88e4bd740d6588b30b6a994701dd970aac571e66cd86b3c9b9a524f144d80a96565ea9bf9096721787d5e484a7cfc24fd04d7384455905df6bc6e3f526481a38648f0ee49335ec0b9c067aa8071e0bd4df9f23960754ca894342673cee8a3f5a6c26dbc476c42715e23d222f3f8365f69f2571e777b4aa51126303a1e90ab3f9a445df08fd853f64ed4a737bdef71aee8e54454f8af5680c0b996f7eb4e3d3f01b95cf449e1301fdd80b4d3d238e7da61f7be64e26623edafed874581ce54c35c4fc6b302b565a8a1eab844d086001b74dbcdd14424721bc36828ebf3c3b70a8fa289c11f0b1559988d4993b696e1c6fe6e62c97f4239e305524157540e9f472e979f9640b26fc6f79e69db22928e76813e46a1b056a938730c1f4c0d5d5c763ed3b78fa56073d2a41c639f4aeec923fd761844882615ac1ebf3dec850e33b7d00ebdc62e2bbb0729cc465ace1c8a50b4b35b4cb6c51ca9016ea38a79b65eba47a955d41da2f23460d822baf79e08658253c019f1e393c0392389e527fa0c446caa5b93eaf129c5ee2e0fa36d08d763042af0a9cfb0fcfe6a36dab0a78eeee90ad2d5f63f3eea6357eb073f9f912af9be8e04d86f4a34b9d7a351fbda890aa01eb34dfe519195043b116af01d47a45e5ffdd73d799ce1b9a5e584df247b5b4f1128861f43a322ad193d94ee12741817a6324e0e8f747d20b20bd5922b1a1b3bca25c7f910275dc3a93932ca5b6257e7476eb35df4da8b5545a6073d308ca77822a72cd72e2c3e82cf108dcb05f50ab61dfb879bf731aa258877628df11ece67758390946519d566af6bbd45d621e53bfed5d874cf1d22ab489ac8deb3f8943f9927aeaa68cc4381cc919d25cc10c2f4938496d9c787fe032f956419d8463ed1385a0d1c96d3510ced99ab14e14ca9aae0ffb645aa8aa0d09c19a4cc4a6f83468148403aa88c2655acc1c95f93fbc192deedd77a7046f97824b1e412fd8e70a71514892fe27b53118e4d3362878dc31ec6343d3595cd0bee06d9bccb6e96e8f5db7ce8a8f31b24f989c4cea43e55b3d2ab85add1907c5543551fda44aab69da22483c2be0000d3c49d00ab453f30f5e2453f8c02b20a398bcd082b6254fd6b923f1ebe56af4195a336246eeae1e92b8aa72fc6e355a0a1fa1a982363bb4c73c6102ca1393267a0a9ddc14cf5aa12f3a070faa3c1865add1080836c2baeaa598fa3f522133e7213b9bd4cda65f0b98c377432a28f6ff093b6fb769b4e9777eccb333a9977bc3c1c2b8d95d2a44cbecd962981948f1667ee8d64da1989a8266056b632f5f7da9018f290c98d6b546f98dd220df299901af1c0c8a2155230d7d46061be46795a5982963ff1a6d507e256edb08df304e8f9358a32ed22b8bae3b06154fb5da7c4c0e448509a0b61cbd6e4e585823890bb1e2b44dda6a8822c762f6e8bf07529c4f5a7690c24df96c5586fe5131ce825937a5e5c8d90ad3848919d937eac19ff862e5e4ed51c7eeeee626d601ccbbd055f68c03bed53d67eb8b1668e06cf7acbbbaafb7855964b6c7be342e63c9df5b935338ba29fc651f8e029499b6f8e12971326ab7a0b836acb9b0c67ec72900af728c55755596894c8c9e0923799a5b7d0f37372ca168044292a1263cab005323db3747cbb1f6c08341320de056418b32c9bbdd9dcda8842251aba76da423d40dbb390a62f696fd3f1e063bb0adc562326f2884c0ce745740c1ca4c3824349c175f75be9c3ddf418894fca12c0121d428dc9df635a7de5d6c1db6d359a07f02456b01dabcbf49b505243a0e295f3bd03cd70209c2323131d9a300e7c626e8a30013716ee6564e11e349d53404c2001f1b77744839154d52cbf3d1045d71446b4b0e7c4e3ecff88385c35a0764aae46296b9ea80197d74da2bbeb8a430e90ae1c341059663f51b58d756290858b054ad60d0cad93aef729824f81b9809d6c0f3e8c15cdb5c79f5361c33cec09ff86195888f214b7cf69a19e9b3d3a91c09fe6eb43c970a1c6262180b9a0d599629f12a61702f03c0ca5a45f8518db4481c721155791368cdbf786d1a7cca77befd436f836b5bbd548f079fc87a3509d12179eb3dff109eb6eef56d21f70a3982b24c3661db64310412dedd44f6aafc252a2cd4f8db9bbef12e0faba2381c18b5a43c9a16ebdfa9f9c2a4ff5912e46fa2599fd16a318eb62a971a03890c8da8b9360065d11fd848857568d08e8e5813b159ce3ff0fea253593625f82b5ba5794c015be84aabb34409e937c51dd3f6565932561571aecfae711b61a9ae5cc1d12aeda3659669a481a433137bd5ec3db59aac18004db0f96e708e06990c35856dc612b24ba27d4d837b3e8196a2536d5e388d8e51c6fb25d54043d0d2dd5fb1f827b451b7846511e5f51b6f48c3ec08fe39a677e2c8e", - "priv": "ea95d53403e54cac9521c5635e9f335f75da4ca76005562e75f666ba598df28d24492cab5ee1a838ccb870b738cd2bf15845081ec92fe655eddc3daabbd70463345e717bf4e9b77e4e42c41ee081fb7609e529306fad0d010253818bed6f5c36e80f0cf2e1cdfc3644b0fbaaa332c91b8e9bac48542587ddce3b89b85ac95b67205358448251106374330761616370840427403060131555776484032685263315404265627140818478237330461730266886678220206757852370307812313186670777525377243410283855032620382282420030862325482173385126618006425080660754150507021155510527010400031730580268480057432412702246646585006018341365521716483413675564656536487671660142316774020375316380713786272377283742823337111220565020523286660270378010320780454435727328225012270684854752384080330327232568564232334624785300247078327824557671535222210477505366750273350760622046230230260051216004274018134720587804852011513328437632380487348538761062461618530322680868132352785267226346453636340478012526081750131434530007670441442545000101046220634032432113214835787158680732862056026304846838602761436702478386234638586703304407840415284465247473208178635703585423748148856167002814048306441188623612783876688861220036258078151885032812826481381533241417755607323112011074124487501132778203584733520654651330088421647830628846050045765114501255050401362864274111122784215666102828748217571715050331524203557710257341457213042182483316853151265470516218556873288758186361667570271538733143722872641133534773365442068318176733601261602087128454576104402730785325228074080124728136803212012176421321531125876743834555426446750774328825708846140833734063225565260787734461625334052344861774220588771408021810607471156332580632280701173562858681586364176474502351131460358610510860814212667307781071767853607451544703521337335512585050362481526644627232206577243115336803784153432761563147764470542241266534771730877768307535531184023433563146435118336554118553322683875347873514134711335415277733516356657622323524047003022507454625047621173572485725784623060878303721555357201478557707263311371545530238434748271222817073038030533437284816784301801712411264351214303745068324677180701387874004318531672172357360350653266358643677401786781602256310774310423523102138875113656455771583275031265507486382852658323110101755161235083527248117325406547684577540263666157667871418616544150267046727347840767160533104681104207400671472835332830774825088686527066365754634711824660710703543823161528234747317210601368642418361673115730670838723373875628051373556788162537260577837888028732672353482401052021665413247585302187633005427258870173180733401656355241728775560065687277881464582763237044678011865760682717142166374624528785211470160157277740506621763080770285055044428134504455441747414021514780758088166611667254100231637072441607706077511335806828544374880608121171511770560080601164106110827266126106183135415882627445120836107122852801612426738230306530455072677400205525856874676132831248508378511646237882435637476882748587424351284047403241180001573406464365334575336777303464222072838174364367877848211517701774258316522054107175211473552828834313110583621807140335000560aa86f8697754821bb4793b67a97b27699fc1124fd3cc779cce56fd068d0a004d91a5a8bbc7c8517437ad5fa4114658257b24fd6cf7d1e7d4d0394dbce171425087c232dec09410ffe82c67427a4d97845cf0922c29bf38d3e6e31e8758a43839569925eb3d9834c352c2d2124ee24f5cf61207fd6bedcc70e1d665d12bebc188f3a1e6ae462464bcbf05587bd0b5e960a9d20db52c7326dd7beec6d2b20bf82b9d551475b32a77aa5540d2c15d44c948a2f0ea266f6ef1f619659b0c4ecfe94d45045941fb3e3d4940a0b7412b2152afd4796104d0cefe9b5eedb94ecf11b0f31956e2ec3aa935bedbba75ae3878667df71006587ae20d9310a2e4d32a9adf94c7995ebb2d72e1eaa238eef912458918099ac43d157ef4b4480f8c87ef8f8a14b083f85cf46f795eb40edf4cef2661566d605cc62ab1bd197cf13596777429d7e7ab5835d736ab302ccfd90e5a0a56342f27496f7fd30064b1ccfab8c3a052353339df7d25c05601b8b7bb86d0b43bb4e1851636ff4471c26478460fd4f90230f3882ad8d5770b366b8a2055aba7045df54915850b48c4c191ddebb20f0178b950f711757599c73b31024344ee04ec84e57b818f3c77c939698e895fe92bcfa7b2a8e6f271c39718c9cd91a278ec554a3746ed04063964ff384de5d9e53d8d018d99f974f022a8820b1ab4f2155fa7ca8d8d454058aa179fe01cf8808b33ea1ce9fa5f57f59ead79e60f374a5ac959f35a22a336f505061d75497e374ddf66889b6d72d5ad04e73a7be7dc43efcebd248140b0a57e31152ef1af3e6eb4a203b6292a867eccdc211dc0d42b67d7facc9156d159cddd0ca254d338ad67093232d10e94b5d6da4492704d9a35501fe279b2b6836978c0520b643323d9e0fe1830b2eead1ba1acbd76de53c8f4539ea793415e2059582406601ba40a2981ec3b5cc4ec5328f6f636fec2751870923788d0f8331313b0566c859e01ffe88335dbd0ba67f5a6f73b41bc9e501272c7d2b6dc0047e3c7796b0e716c1d5e2d9601e84876b9a94e91fa7a48883fd3829786162bbae86b4f6e0b97ec079bef8c57fd43444d2602d3a9c5df317c870c34d8b530c92b905a8b192f0cf1cb31f67cfe717775652d3eb6bfd7f3736cc3b956bac5eeb82b73a29d6bc8fc64375f4ce18a066dd7e8ad4de9b051dfcd749232af775a24597bafb20cf25bd08edc60d9a5030bdc28e600efa01701c9f19eb20755f17ff66a3bbce48cc727f7d0b51fa1652ee2a9b8ccfcbbcfff80ea6f6cf977a757a1f079cdd91094e4bde475df195ddfac60d47101e459ea750a9b6668f66b7832b1f96eda29ffeefbb4f4b988cab6e0000377b19820b0a12d0650a60df4606d92372376134d184e5e7f94688ae41c3e7067f191ba295c1cb0f283bdc5bb02d6b77dbdd22b36d7028ab787ec423f026c5615f4bdf04859eb68bb550797756f148abb10aabfa479271b202ab399a3d5b6b269c3b04b6e6b8282f38155aabf1b5db61513de96993c82f7f4528894efbd76f99addce4cf7c6be8f73c341ee5be2e9f6298be4e1a00d9751d65a5414b760ca2ba96d26a7b2e77884280647bdd9e6aba0dddf1e84ab104c34d0fc10de4d634c18ba991932dd0baf307bad274eae729ce4e642a070a9c0f5b5343816d3dfd78eac59a8a36cfd5ccfbe250f5f6294fd58587bece6c9255c2a419b7614a08097aea3851324c533003874849cae7606f190090299c473d3c367e2a11d61363c7be70a0a9e8553e572b926ba73aba9e149890e61a07088406eff8a352189f6d68fabde060e3f3592b9f729d83272d62a02c933a2d425b71d9ec5839e53aea96cc7761064dc37dd434b6aa283facf03a5230f54ab0a6fbf7858e1434eb58d989318fc7270e0c76acf28ea8b6697408668b1f556de9a53abdb587e7f8d7816418efb92af93e8efde2f0843208b604e483e7ba28565e4ece92a54501639cc754f0d5bf5bcea727ad2ad5030fccbadc4bf27a16057b3f948c45924968d9f69f0fc150944e4d541416cc46aac433325ad2788a944a607e001ccd824c3a1bdb3f5e0f5fa93a864a7c7b0c2f95b99a5e64944f07c4ae95f9eab462e90487ea2fd02218bed373536e1e92eb7b9f48f6027941a289e2a63cc9ce55083d93514d5eb734f9cdd5045e4a910b824bc105858e6b4b2a964a5303a9593e26824d5956c18b5e7cd5e926df580043c54b3862da98cb9d84a68954e96026eb0b9c9cb21c6f04e783e759e49b7ff5e33cba7b10dbdb4dbd84adb01d725625b86b60b8819b23abfb84f8540a953a53e9002896f00636d96928f5d6462df2f1e5e3baddd3e7ee5f9bed9ed8e29499aa327083cf6e3c6759f34f61b3be3ebf6629646b6d7370667a36bc53056b1c045a5d460aa6603dde5c0e80b864ea6550d2529f9de9202a8731d21518e489d90b16f89d1c31734cbd18de5f1f31872593ab9037f3dd87ef3e91877961d075532305bab20ff22ecff44de46cd7e4cc5e19dd5c101ab28487ddc6ec920db72a30ef983e8f4d009569f2864b35b113d050032cdfbab343086ba92d2bf00d7cac698bb5d436070566604d793e945c98420354077fff14d5d4b7366ae9ffb7b3f6e8b240a82e85853c73fa6165975a4c11108678e1e30b82b5f6346b283c41964fea6d525d66b46c2bd259137cc02b4ee78532a1b76409f95498655f6a28c4eb4cb280e6f78019d2d5c70bebf9be1943fda6897ec6b56ecf64622b520ac230bf261f60c2e66ccb7be18a0b16ba0a08b6f8468f2a0797afc66be782a6f6684760cb189a287f74996dc6a2ebb0b17fed11641d89819761d3c0e4e13f165bb6afc6706fb4c9d27ad6eca1f8f8fb4c919d88aced483dff586203904efc7741ed28771317645fa2fb2507391a663f6e58ada8e219c9b379f4df03dc578cd0afbe62b65bd18943c81b9b7276f47e81351bca38770a57894b2f54afc746155111e928a7a65e7b4620c976bab3bd48401327300680153c2664d303b5365c0f967d39bd92dfb53583abd16838110dcca3fa0bad45f485f686d1003d62c3f7e86d87e908f3cfd77223af4d4f6efc817f14ee85617add35c630879fd6ea0e20645316c26fb4b9e66ab6fcaf5ceaa95302e3258eeba216082a033843d592f9d9b655a5509390c63b02e904dc2efd9c1a4f9b782bc6af1f7ae315c0e7e25a5a8dfe3ff2745504beae8d41ef908c45f3fa6f2e40262c88278e89b02b3c8415c2c8caa76f687ef30014c2c9adee89e46b06383f4fa33e66fc80b7c505972d8164f6b651a4d037a5fb2adae708f4fdcedd202f9d114f4f78bd2507274e87fa4701bab73390650d02e254729c33dc1378e9c97bfcdb32d2755046e1fd63cc0504b8117f82e7c1cc796de16126aa3f50a9af0373a819b01eb63ff834edb711de4e877ef2f1d46aa1b7e0eb0df171ad0fc1f2cd0b6b029ca782fb259c5f860428478dd9e2270a0b9a05260db661cfbd0e80e75f06020221115ba18b0d6b455040050b23bb87d9db5f87877e7ed688" - }, - { - "seed": "d0632a6edaffe0a71e94e62a5135066e6f7abf8065774a2596b6ba2f7f138bb8", - "pub": "ca806cf2d4690c7bb3ac7cc12320888b62c8202262bc7f8766eb6d7a3a067a74348698a5cde30d2256e33639e45307470dfb674e427a6a441012d80ade3cf8133b307e29842ffba09e7d04c123abdb4cd41f27291e5a6ed55827769503ee1112ac884873ea789644c70b424a6056038e2a0d785ee036da2da53b724cc1fef74831897636acc26947129b21abdadae0d105b07fa4c1ca63651d23355419307e8c44ee19373afd8cb061f1b1e8406627482a1ba2e2dabe2e5a0cabdac7d2a7025a8bfdda46d9acb02ad4c9466fa203059cd5673c2018923a9304890e3a92dffe7ed3592cb07e0b23181b20927f96f0e85e4fd59effbd51fef48909e36f153dd128c001b59f164ec759c9d8d07b1df6252f1b8da19b9e9019fc5b2164a88a4b4c34da7a8db6b96e653750ba8039a34d5699add2b5dcf3c191f4c10f4f3f772074b4b726e65e783aa34e3b09079cbe2e68f0f52c647eac333fdeec274dc4e123e078d47fd52d01961e2bbbe62a1472311ba4af5481d92659594812a4a1d841cc35a3ceed21f5d69c7f1c4603cd4e1e94b9fdb5fbe2ebf720d5481fc0a095fb987d2f2b0c5e54e9509b87efe228a21e547a28ad9784477d275a8959ab2013bd8c8702153fd2b1870f02beb1d1b25b2ca038aee8e93a6bc6e5154624c6a734736124c3df027d3259f5f89c51b18f4c3772795b1e31c7c566ff6f2d8be4bdbf75f6fa4fb5ee4d9243a73f6d7c6dec8d4e0e5189d50d0e419fdcfa07f03246b00c9d866e87ddff61ba2b7ff863b7b120520c67bc5eb4690249ef688065d94aea220eb3e3a11ad5ba7a29d9f262cc28a2e24668834dd679a87c1a0a3f36f905dcd7829a772b1308ffd56d021e58a81b60bf95276ebf04b1c1d6308559fad1e80f39627d82da5b0d23ca64baedee87efdd8c34bba8ccec047843c84af46c435aec0b23f9471c73a78456734a715ace1af64bd69ff7acb6129b1c78608d5c64bf7ccca2f9696ed1c64369007541d7d76dcffceb8d2e4f911defadbdf740a4048b0006efde5a73b73d553505b7286211b85f64c7b9cbba721652b8473b4086c95fa7d0743ec2f9cc5c887a727dc2c7321bdccdb028644ed73eab821be8f951a26a516779fcd5f68ec495c9ef78660683f08a85a610cfdecfc58cf49a79a3b9e3b5ff9e403be51c274dafcdd07e2051b44849c2aceb79ccbf64bd6741b58fc4b6bcfd23b4496918e9bac4fd4fea6eec1abac8757c6a972d3909bd94169db5edb540225550b600bd347eb3efa51a5f6171321a6f1afd6fa0a7aaec65a612dbfc300aa4a1921cac1d77eeac226ca0f8993d1929f4e0f0e85fa38d436c035f49d85d1a802f4dda9e4da98bac92a0fa7d5c2bcb1eb89f3394226766e4aa513928dc910311b086b19611a58f6a9a2b494e67e22bd10ddb62e6dbd775e7269270e2a0270d60191c8b2c8fc511d6ceeebec5aba95375412e14bde0906f2007ee4a61ef0e535fb22e6da4feb9babddf775e0394997574af4750acc98db4c7979b90d9daa0f35ea877d4d868f828340d1e38c767f413e89de0645e1e2241a79fab882dbdf87a04b279703435e3528ced89479d163917c1f990ddba9b625509ee7b8ac53c38060bda1ee697a6f237c5ad3e3347a7c6f4450a363f171901165c2da96393fa31a057b1c1964607d923e5e4c658177d5bc0b05a6cc0de1bdfff0f1d0da1f1c8752d3afeda44129507ecb0a8fb52114f5ed6f0cd1bb486af44a3d74c8f88a2ad42a1b72fdba3d6bbd2943153b55a9c8a4dfffbe8e0b0794e60c9b64d7d716c58634f7aec6d33cf50e604048a2fc28e9c03c7a77511d7ef20482fd11f815852906b0b9f4a40d45fbb972ca67149cadb90f9bd3ea69e42291bb1562464bfe78aa39240cb24b0bbb8d76bcc8057a3697a2b5dc71c8e9aafce7ea04a0498b365520621b1cd4b38c5bc3b2cee7fd7599fb79d67269bdc4e5e2ed33f9c90d6ee42c9829845d7e6d6e861ee870119e99095777327297927a552d2d3d8d850d3e4b63c8934ff69abaf1a69b408dd2c630b3b7af05c1f0e22dc7e90c4a31f585fb9d9e4deb4e9607cb49c47e6d8dcec439aebd1edf4cb0075b1164a3f29c33dc9d0d59ed5763ad8b1646d0f655a00b6918a90a417989f9aa44b5cdd08cf1be46874218e1247a263e64dc1228b540e70ce9f0fa70edc4b5d02cdc450af18f6b586fb850848e09682c5b6adfb680a6262f90856feae11843b277ea039786313a1ae260db0062afae786b61d4a4c3b30b8194379bd44436879edfd61ffacaa894498cc26e2f7d823f0ae7687ecc67930799dc402bf4f95db72001f508d7da37eaaab0c2c553a53e7587acc342167f62ea39c37b3e61a5d7ab113cc38f8b7525768a67bec285f0abe9ba6a9957c77a45602bf82f1059e55ae9b9fb126d24e3003d4b21c9cee851527a324a6f48faf80387d09b59cab3643925ec74fec4374ec3e63853e741638ee27d829ce5dc11b8120279ea9605061513c6a69796fe9cb8dcfa0ec70eeeddd70927703fa4c64bc723b94d358371310abb486f086abaada7b78b1c0c55d88ef497ef7b10071d8ae72e2e28078d04abf04581fc9d4fee6aaac4637e6f9f6f65aab1bec7526cc1be743a0ea8481aa9e069a9ccb7dc1575345305fbbe7338c1d82bc10a1b64e69eef7eae67c5819a3b49ba603f7477f19b217afec4bc32dadd26255e2f917806adf9e64f769af70ae5691b26070a6c65732530d93ae6d1ccbdc77ae37c494b51775", - "priv": "ca806cf2d4690c7bb3ac7cc12320888b62c8202262bc7f8766eb6d7a3a067a7482939de8e5383e4a4d7cca79a9b7b5f621a461b2a1894e53315103f03c391e0a38f615c6ba1e541a423565fc34907d84917beb652aa4c7c89b35ea83f793fb3869705e5dedc1d7d34ecbb4d95c1d35dd6b40de0ceca740a4e31a27a3b9b98b004167782002506841243131365280841862554703104113155456536303543617108241084365386764253004844717327286064008824375547612437003687713635685066644742221774873358808665720400037071175028268662180577204401046247407058352323335075052670824212300407483106303227830177854464331616047542826861670237417840476056071515848278403033816884841214314076440461221508580035331828782618221062670850105785181770543082612856215036712840812726467805080064220170772536041034233473660817847175128245640505226614302508264364233558221033502567126054184687247511388085075262104876576227676324033577673623810188261171678788152746506166666437714701318570634332258550030740802413325435742263763045437462580115223212302255580103400865160557838787133716521241880267285308440147661876354467437784576735016345306611633062308811754584122563375147088373865225564243753521041540308730534446822385070861372114166326555121551770304536258008600364651176054363425836546104588565084542687503166017467336054565181617671174833865845685463658560857723333778762132475402167621010761623608348147038670132886240342442203328236027687753446546143324435782630665465553071476465625052657022353521572181631224342003132015665731086200251034727642342042768724157205803313336582551523358281602585074476178580187227145207635537012102513281730837422237248644518856730446206270316046650705818616665454358454738580353684110371157587563500822416111325582357584873627108128414201573148520755163811133056706316481086737445764287175387115416137177806484511265720218435445723261765302547621018234141462250030101638825222058372031833322338705318630036282520683874156368725686845163013242685832845523211553403620674105511622738815740862134023810117557426767760474585642644381655073854814045378307374382347381682033386078518685732885231765713423524881768718425148633644633286058714086311531058034818681263601377352475382525127272081155327226706655400072010405570087661815758158316283675713547420087156758728037757338135282288202782248501716018427204542088117607023584376282157782581470415233186584826507805762724272460033571412651326634402130004312645872667823075287652008020443487546340027782053437118628753610138356363183678428866266814623572045615003787625306877435726552077775273853857342148168433307612655423471126126802170023576688573236778627018467128804074385508720177344051461510855273367027750453251260135356145844210610652605165255220226672777165242368018647605284032071386241066412541114087584161112462346880726742547517663078120246705222743787525124154100750480507431087464341512207843441744722418777548374068250520572687713551245737701746245167380432348183857040811300514238606167175033186851181631382615450327661753468814784210764752450808523060630255288500182478823571263715802420751310703278612077507052483158216127060610280280340534522742587786314172781347215116342513c16b0a1b5b614ed286be55e5cc1777a2680709f20fb7c0be8326186386a4f081761ea493c531a8a89b64ac384c313f63ef47d643a8e614a9d8d00ec276d1fc7d84034ea545b2fd2bdadf7f90d0bf68ec519e47a35f14510bfc78314e51ae02001c503e723a4b6cbdf23a73d7e0150a27cd344520027639033e28c34e7e6413827c4f8213f09babd184118676d5e1361b056f3cf3d5e0cbdae14ab817eb1c8c4f9a94b65900259f62b3e099da04a73cb7a671dd3814fd163472983bc8656c8bcbf2dc6ec110827656b37add2b79e3b7fbca07d40da224f67a06eed7e57b0226434017dc436754c5a9464c687bdfd74e5ef2adfa208f44f18a40e36effb2271c634f1feb5dde90c929ef2106368c73a7672217bd86489e0f17b5ee32a61af1950df50e15e3e0db1293e0d02f9daa92999ab5bd13ec2ae956ba90c226fd88cbc6bf31fa87b403ad68d166f60b25e539b769adc1a80918218df163062a8671f090cf07686490c4aeeb58d396cd41c2111316444fb56200fc8b902a2ede74f410c30153b8ef03552470f1c00852c564eaf18ca6d5de6386f2077837388d3ec51894d90c2f86601e4ce8d6a974962189c43af8c9f682573c794669379fe22efad679e4cc797daad13e7f41ea7990d62074df58e69f0f33ad8a1c77eb95fd8253c692e3009239b5664fd4b86acaf7403591c3fc2ac97fd750f09786a430351079fc257dc7884a45f9b418eeeccae1d5f63759e3c9d61443efccfd751ac19a9959455af7a49433032f8cc4f5678f65e9d6fa74761b9b9a1252928d760113dbed52caa13dbd0b1b9d63d7f97c4a71a417bb8c823853236ed58721f903d8f3b8ba4142d9e4d3d95b59756b9a7d5fd0484ae286ccdaf3bd033f9b743f5db8592253848fdc1e2dae0fc717d056d8d36fe91b3b15c1165e018beefd0a28c43bbbb5d95a82cfc1fa2782f2593dcd3f982143e7ae80f70363aedf228a7d847b185cda5aa435bef32d2e4033c34d3c164f0cdcb98dc36bb52a2c8e12e3e3b3d08ddb265528c7f4743e34cb72cb663ef69e086e6d46002138e35b2130ff2cd40d9854d674f98805b0041123ca280589eb45f066e7048a2a6e612e81ab1fa93beb0fe673a9092c6f72856b696ccbfb6558a39209c92c800fa0ece324091b88e67ff414aaadf439322e4dd3d6ea72924e4960fb7a4d9357be2ec4c3279bb9bbf39af61f0e390c6de1f94a4786689c0cbc2e9abbf3dc6d0d3538bd872b882284231cb76c5ad72560ca2ff6b7bf99639459e2861500a34384862856d6aaa944737acb263294264209e02501d97fde1307c45d733c4d35b4ea5ebf63a6cd16a8d0d3294cd4c678ac133bc2b6315e53f4e823f3fc259fa2696af74e1ede6c36a5452bc5a339068320123a24d097a379eab362619070a62033949204024915836ae207e0855c28512daec08e70a931c69d96aa565c55b4917cefa3d16f6505a77cd6da985b4d2276658a0dc6055f5bb0463c6b8a521aa8f7df7d9cc08bba26d85670c888fc2b2dbdbb0d42a1b15067865e0991fb0cfef9cfb7531769b5b3311845adf229dd808243927be8604495f7fefc90021d1b5ce27d372dd9ace488c83d99eda25a84c794fbf626becfea5e3b1b360d520264910496c4922a59efaa779cc9f5491000ab2a5043e18718fbfac21bd187ccca87199f63c29bd1f402dc1115f07cf993c9c46ac89f394d96a58f68d9682384ae586ba5e6f575837270b8f00062ee4a072af52c5915b770c30c372ba591120dc8b0eb63ca29660ab16fc95d8f5f804479786b68d0be9dc758775921eaa7b1a4db99dd6ffef29af98dcd566210efb33cf062c2555f0495bc654fc4952aa72e4b5c9793917440d63d5f5c4ecb0f901bcfa5f3309d57acb366396b88ea9ddf1b9a07f649d5c0ed5b945fa4beaa1f01a900f5b3fb64fcfa7d087a41ca397895ec045bf595c2b4dcf5488506a3c7ee9c4b588ab0e49fcbc7547ea2a8f867813321658a6240f12a1c2e47b1960bf1ba97fee40a82b0aa13146ba443a891eaf7e885e82089a5ec21d75760ba5b0197df5306b3438d3fa2b799c6e171b6d9be22377704ac307b54a6ec6fd1fc98c57bd4a8b2e5cd5777799e3b86fa8f0d0a683eee2167bf15c064db860794d93ed601c425598f5a4d5b354cf0b8367ad742144b1ce70db908a466f4312ffd7fd55fdf8f820398baea18adf3b14710325b93877ebf94a8f68bd5a57d899d12ffbcd261373d2940d78a940d936f9b2f88599491928a9d54735f676516330e6d3e9f284fe32001bd5a72c0c0b29e2471d77fb31351cba2d41ab5ec5513c568ee993457bcd6950d259e41e0682763f057d3c2234075c6380d65221e6e475aeee13cb9dac1d789b0be04941985146149f3baea4f49053cf915721d53e4969b9e5edc83342a2328fa0fc758e806c8b9507464e9beb51379b650f6548f26930b7aec18fb76fc3cc6e74c21a01d3cb206e2381eb61d9203c3bda62b8bc2ae048ff6b3484e0ebe49d3689f51061a02d31ae18d0f3090598e4e0da7079914b8bf4d9826b2ed5cd4fe1def48d63adc7d66fde0215a74a333f13f743eef7cf61f6403cf927eeae489a978f0ef1fe039e1aa74ebde3434412474f4c9ef6f5a0f1d765624e7c7f5adce07434f8744d966b685139258006db7107f7b0995c923e19a1a778639da3b596f4ed950b4fdc87057ddd5be1d59a6e52bb6bb5e3fcef06ed76171de35d7342e1143a7ff257cddb98194934ecf249468fa77339bce39223c299840d7f9a584a3c9e791399874235b3f1c0551486fac4bd434a4ae8f04f011a849f2c8343900f0f9bdd9f9f8b80a7e6d9d1b127acf0a37170415a2146b03bfcfab50aa890ea64be874d4a67af2799fcfbd7772b5fed6cc2e6646845b007545eb24b12f7c5ef5f9b2ab7b4ac774b30e8ffdebbda4cd07cef7023f20eebefc5d32d138f7da6ac5c55d9896f618e274cc0ba43f058917667894f99bd0ca6e25912d6848ab545449d1a86bfdeb77929cc9e21fefa8315af65fec0a4596f95bc3011a9f461a67e65464d36a7f7faa07c487cfd2fcceb9da28745b4a7543c5ef49835914b25493a43de0ddf4ecadb68eb4dbeb7efa3dcee7765d07df439bb632f9723877df94bfa7ef26936610f41b07d56026c91933f019c923cf98c255aa95748e99475b77f21f787d3606a3676a215785728734a7446b0a54eaadf962edfd0c11f31187f84f2629069cdc97f99885a5f0b8a52faf7b9171b40ac47b14e00d6c708a109f03c7e7130b1747bb5243c73d18bed9f97fb2f2d0449a0a9f4d4348b0291c47f2ce493209a7efd0487d19a41383fc7c6cc8989f641918078ed90d2154e3cc3d4d0627fc86dee37196ee9469d5446ac97a1a491e3fecfb656a4a3fb198fea6d3caf6c9fc09f79935589fda995c90ae9d78bfd33954d0f78d322edca54e3c4f78f9b99b9c60cef18c611abeebe7892d3ceaf5d6954f7c599be6f283e9c1f60ea8509d8ea192efe792e389d2e2f0180b92631226" - }, - { - "seed": "74c0714236873ee53e7f8f65b1159accb1994b4e9d3e8ff194cc87d7116bc0b4", - "pub": "10ee0cd7d3e3c3d54fdc1b5367b8ef0db5a20c92946b3471d8aff7026c8d7406acc5943341cc53c189a843aea7399002eefa251842f86ce14d00d974b4208734a416a048806aa9be9d7b5b9eac0c6cd7a3c163801253dcc0ccdd9ac2b4a663992b9e2b7ef3e2e8b1d93e4b677d1b36e8388a919e5b3a2f90e4ee69ce88735b8b105e98299ed5a9ac192479052030e6c56cf1fb2e5a822b3300950eb73a8fa59918c5468e3effa4a410e44ff78750d7b209f0bf48ec6e3062b76690489e1ae93a278d4ff6ef799079a8b42863688bc71154a32818cd76131fc400f2ec7ac3de5c2954df90aa3324756c8f31404a9094cfdfe98ff12d1f052c94c68026a214d0825a9e009a53ac5b8ac30777e05254e0c966160397fffb0436a2cdf4fbe10b373349524aa455bf3a1a90ae05d9ef25843c8e9aeadb5ff113ed03bdafc1ef32e3ee3f073c0fe0906d4331e2f18edcd335f094cb3ab30214e3ad3a919bc1470685e514f86ae2008172226495349f4a9e55c3303072497571c1f4a2a28328e7d83e2b392943a5ed46095f55cb28a38bcea6b801c1328031889a252851093fdf0b888e2e35c0ca28b5d204955bb6a41df6ab0256b985d59faa55880379b080dc7c1b856642985198f4b693afb943b6c9463ec255013265c586371774aec9e3251817abaf21580d50a849328a828e5cab4c9df78c177fba51527791437afbb01b2d7e88824bb7a138ac8741606270ea33ea27afff8b3eb0f0732f60a8d179b95a513cdc9a8072c202cf4a5dc2ddfa51ba3bd186f6299c3f7af805993808f3af31e43bafcd1a53a494e0d6b2b230fd9ea2e647614e50694b9fb19a810a83de294c6be35d3053cf2b16591e57a76b0d67c97b1bd8aed950bfc5f8526f571c72e6646f2b9fc09c9070e4a761fd82d723fdc96110a3d50d2b58caf753de0c8e55f32c80932662a8c17ac9b219456aa9649629cdb604322676c3e3bda5eaba95f4f0da031dab5adf92d8ad4190eef2742cf42b26ef53a310c15d792ddb795114505222d05c21aa2567bb52e0c20a7251a672267d3b1f6728f5a0c00e957a534ba80d996379bf00be4a725f2822643803f1f6780785b0583e0d41a67831e9b664c4e843c8bbbbe525c10fa7a7d5d3f082bc9ce72046efe9c40eabdde491c1346395412845b3e94eb9aa0e54381bfafdb8186d59cf00e9eeeca5c369ff92930b569215fd7733bea2b7bd8dd511c12ede27ed5bf1a28080737c73557007890fb77bc5942433e8af06234bfdce21fc132c27a754709aa5b8640eb2c24d5f2d3e6da9b9584317f27fe2bb5f74f95f512cb81bccb2a0d70333b52415a39129759d6fc97954d0cf9db5de9f091784ba15d360b2fcb7f0f43f07ffec2c3161c5c80c9586ba6323714391fd388a5dafd74b436ca9455a5a025dd79d8f35632536c1e4b1bf67a3ad009878d1c067635aa9ab6989eaa3b8d788887ed3a968155cabf5baecc99ba50f5257e9f712dcad05ea58412b05ed7b484f54c04fe9f235e5e65aebf23a55f60953f165c0820a9b2ffbfcf3fc6de3dd30c1a82731705146e8f9d32b61e4aa16279aaeac2e04957025c3c8d8af4064924defce4ca07e6f76bc56833a83b3ca4b9ac61527577c1bef69312fe3c61a09954b0cb6261bb1272a736e66577f3dc268c026898961886ee7822056149c35cf6f96fed8885342d12a22aec7b669a4700d19dba1c275fdda86eecf0393840ea0510f6bb5033c05914ce4b1f44615c12347a45405cd323738c2be21385dea60ade73ca54d52f14203616471e0d0b3c1895bb7013fb7e549347d4f8ad066e20f8ac282b8ea89b83014303d2d9fedff90e3fdce51124f167c9d32235e8126679d8033567fa1e5e41985cc108e5aaaf363bc677f961c30c1c34e7a866243e0fcf79271571bfb713d86f28f61c5ad2999fe7259f15ebc0622607553af79af73f01e8cb369cf6716b91f46444e6e5392aafb8dedae015a50db6c032ee026bb1c33c5d26b7b6656f6eeaf7c099172bdcd632f03bfafc76f8c2a81ea19bd8981901b4c4304912b0d4cb25a27b3562956fe094422570b08089f1e28d87f46057d4f4ade163e9045159d0967ad8377792c4fef17a25f11e36b21dc0347a70d7bc79daf4bad4a6a153fd403f601ae7bb3e78b597521633500532b75a046cb78183c5e1eb84e3aa84d09edeeea0354b9db64e9b5634e2afa4fd66d08028538d1756826cd9d467df890ae16a9af40e4399bed757eb5d47b21b16d271e58dbafdf8a98b669ee8fcd42108c746aa70a050e950828e4fea76f3ecc3cececb99cda5cab069a66e216cf977c623035346574198b607cd9e4582fd7f4fbe32da87f7681451252d9440a33bc7021e41280dbf732dd2ef73ce59131f972903ee6e46d61b1e7ced204cb149d8429bf4b05e25e28685b021aca8bd5f70d8fc737ec696dcf647577cd3ecd2cad3116d9ebf7177f6aab6ee5980822e57afca971d4057d141f1f55b82bb8f420a064b6e7c71077bbb137c0ded97b2afa2a4988cd3951d2447dbd3d5079920cf75e569191ee46ab04393617b188ee9f2fe6f0e256c8c95266732007a1cf3f2a388caefd375ba4b78fc8ce538fc3e70151e94706a111b8a26f5076c4832d8b6691012081ea71ac204f3e318dfb7590a873e0e70362807693a30b7f251e9f363e494428bcaad217fb9d035e4195c2d0daa0b598b426b7eaf237f88965b4a4d674056ae40f5ee78ece6a862144ab77f48f5b37486075d2", - "priv": "10ee0cd7d3e3c3d54fdc1b5367b8ef0db5a20c92946b3471d8aff7026c8d7406b9ef82c67ad72d44f22e10f89e426ccfb2811a8e07750ec2935a1f9444ff4131cb48a42d748bf952b8690ad6524023f73316d90ad774123dcc5319ed02f202fbfa1f1d197efdd905014c177fdaee49dcbc747225d2fb3cea3adb8e2f10f5755f31436765238773811321733542255302236533175246241780115462104128007273467573581348025535202227888706643664845147473688287871520557661451418514328878413038641373366831185718407742631304024076022441684115028005630816212057231680771587242263888473502112263046460617144852151674704418681846542541312625882506057864440533060357780443856681154777055701564087151872280855644718015658280312863677851147420664002785211407513254877075818406464328248013813154001322331624050147360555283035458016011331203524038706005326522546840872070671102851110243378174102083335884817020806875402760403831201100510876353316634888227144764415084733285837346265644801676051255766352818487278123042115281377854803730378374471578305031582424347547435583025488480537442240264682550287888171205276633203648543708665200471783114087658344004102353745875558615862028665386814251361853842784661712201842436134335654038651468851708818528563106713814084732620424444237602114074526706512504115573852618086623748284154003702757757885036608640844880578740408271280183246214564565328110404504021103016366323280028504148533853428165340303521887433431373146283407730451035150720684600438720240345177513074482742355148418025323238586232103826864137218026215613418453320312007670683531321512305778830220658672678877563067006255872600208024500124245128464104281008478520046576600633618564710588403104531170654438824562483140304830274223077451374414444447124376042865584403545752862327612288316107336565543304420625625012177810618312506023087408115701507637225608287258644060687666174638270058500353333121758648835266567510606053434880354021738386588676806063236654101672728166185228385412582015006285747468822340712803265176441520244078283446424774241033356353475612312701617237258760886425214443261704054342328120028688506282815074881887174845040542014534164721023455783006371746652275687272147487705001375251724275752155608832577703522335257124614767107557731356735056633724055282726761568051586048862533873550710632478825084814164307166347670722803851310738410137755085005608733655557485423453372808253002062253267038441144230483053567613201418323534713125770348632334075865343351277534834615026336638362833351283363448556373502072322478778438815815664723328454262752274860247747123500500630273565256443614682104088854483626725222523065686710162472081316104233804041537588555546274842073138881460052176546281423571573185338586307437833408755217507062427213105610460654803111545817106235831580136240252415456220148378568237665852106565412111146242167358174564532174715154103728681582144676477318056841602550434801435838750170373643147742013068813731813005134634107011047674042315218355460415773452841407821547664873708810126218821246161302682282412113460675813240713848158403046611047337524175380380808012270778466665852652317643364873677411852533564414508451220153f0e1707371b65f20cab5d5ebd4e8e11b4e4f5d822e845589d4def994f5257dd296a7a8b7a99b416b8a67923c9c493a9e4d235d76686f0a80c3b1d922147a744d5094c44f262c209cae25b9424ffc972dc73f836fb02178023fa1c32f80c9738be0b43a1d592ec849d675b7294d2f44cfe4c1075d945b06c11a2dc643477a1e4af420c3599d3500ccf5cd9be91602f3a3da09678e49e076642697d5af3beadb383bf51ff2cb2e2c2b64175524e1f55113a4920af070bda6ac714cc7f10dbaa72879b73234b693b2a929fd8637a13a93a8ccde2c5b3e5003bc9224fe8f0a0480c8bd9d12ff50b4dfbdc0ee6eb93038017377f024b2439a5e1f4c918818f3a775c63b8bd67f4d532c0efb323cea9b2f4860619000df98e5092ed4e55b5d56d658a7f92fe58ca2751a17c91b82043a9167e891015cb90b1aec900bf74770d7f442d102119f26db95e31e70e8b3d31604f8d3f3e74e6b0936f5ad20aaccddd7a70396f0167419bcba7ce8b32334d2eb0688755838a03713a9c47798e4b1757734021fc6288e516492b37bf2a046e56419a1910564a564d642f14def38d81c4b963dac9d23b3960e549dad867f4280567033314cdea6092afc9d9a42aea5e551edfc4affd3542671edc7740cbcafa2299c3111287115ca755c7f9f14bad648427a5d8dc9f687262eea0e594d29b0b9aa6405219400c0fa2b6b8aecabff90b0906cbc77a22926edfb96ae021e20f930d307479d1831956eebb08f4444a63597b3b3b2788c8d05cd519cb40ba1f74d6b8a8f6e71b809393a47522a8aa8220d0b1042ce95a744e81b65bb048b6abf484f1747923d394be5da2c34f0bd81a28a2b0dcd1589eaa9f88f2451eb22b5a4c7906e818e0d8ed383749a87740f9261fb122f3e89dde0d1cadf056d40d293574c0d8bef6c7ae7ff2155b5098a2c83960f77e778ca8602f0eb6c019529d01b73efebd4f97fc855e4d11b2b8f0c791772a72931a4617535dfbf99f5fdc39ce1964d7d6f42192ee5a2f58685d18062e50ae46dc5c65d3561d4d09615111eebe6d3acd0b7e197255ca4bde22464da1c05c1601d72954e7aa5412541eec3f43c3da5956fb65c3cc0128aeb685c00d8b6c0a4155c1aa505d0c93aace11bd702ca0e7ffa2b21e840dd71165d5e734738419d8a01549b4d1ec3194c6cc3243d67054c4ae559be3039ed73bf7e9594051c30e32b31fe7b83577384336ba458201ce23414cb2dda8e99f660b287b391f023de4ba97f6fa87f7c2e98df43dbf31a852ea4ac420da3597ebecae663a35949241c987ae63f2e0ee3a051c1f03c402fe17101680e21163886860b9763066eb9e2708865c97d9d2e06c938153bdeac0c4bd252c5a9ead82a5b2e757405e2538774e4e17c403c0fa87d92275c995b09345e288179c36815ee2feccb138f5647275e4f87540a913dc6ef4c280f09549cf05a6fe2040f402c81bca531d51a3bdccb5552b48d4162b64f59c65e12b5b2db7a6aca488e5bea8637ed36d5d1a774f8820274fee0899cdf9bb802bf37311e398f2516de4d4129b2a7043b39d10e0ababd0ec17ea263f174ced22937c3dcd184531a79cd1a96f3cdee3d1156e65623b1723f666fcb1b0de4c0fe5303c99bcffb31e583434e09bdd74932c1c77b1ba299087f584cf2c58c573413f84d98e499f89b50cbe9b261b0fe913f2b4c9c79c8177b749617f91abdb62f1a7ee394fbb5cf355bafbc6ce1e0cbc2d536c56ca0c72cc618132679df48cf13c5c769487825f8755f616d62261b68b3bcc9837c5ecd952109fe184fd8afd3daafa61c873e460c4362cbda2d1a240bb919fd44914df357d4bfa3943077b3fc3d052c98f325a1d0428e528a4bd88bc1e2b453ab657d514c0c38dae4e628830881e73ce0ff6ee2d1112692d26dbec1e66a7adc56010bd25f9f6a7deb15c2d9d8ee5cd0ae8ffc88f1175f5fa7380b8d1b81f0a70fcaf97b0dde29257fa9729f5c423d8b532b3ebcac59974dc03f487bf29ccc5d7acd904d656dbcbb79989767a198e0ebeda8f96840a7ab61ed3db3c863b742b6a7ef8fe2d3f01530d554578c18e174f8a8c49f0a2b66d246346bd9d8122087714ad87fc884c42714be251d28fb2ca0ae72ae94b340bb6ee71364f9e6d4a56f302ddf19d068e4ed6ed57d2bc913852902026e41b8ad643899fc77fc4ecf764f66ea6280d71c4b3a4bc8cd08bb218a22f5254b819626e5f809d9334a2f84af3960b52849b7534705ec80075859ca6565efbaa5594869242801b602b3a0d25e749439035d8ef7caf3e24b40c7d4a666f83b0945232c192f60fa1341122c772ff83a9f41ce6edbdbb4880c2a67f340a3163a28f1450499381b211458cb711723eb29c6470afabaad2b0be532291a17cc537ccb4f8ecb9263a2ae4850c6c51c9f0195a284a90a22bbaa60c111b561d00fc0d3a9e82fd49a932e516dea0c20e3f48f2d02dcfcdbdbe046384ce410bd650eaf21252484fc22a8e5dc4157ae37c91380f74ade3170f70515afd3143394baa087532c523a2f33db97af8dca20dedf113633371974e23fd5e16b5fc5cd6a9fbb5201d0b5c55e2faac5af3df589c1a8f3f30cb4566ccafc4e1e29618e03e936a1ab09af052d0ed3d382da96ddf004d59201aaba01a9809bdf5befc65c18fed60f885003827ec4b285c108fc5ec86cc54f400ab14b8424163857c8bde700bb1351e1c8d9f4ca2cdf4071e5af5623895c5e027c71b69cd0f50de48ade15e59f3fb5159b588f8d707bb6f78e178013d04e0b57f4601d7e473ad99c19a1077d6220ab78ec6a29f79b6f7a100a5b722343246c0f5998d77eb22db6fda2c14a143bead0bb9153f5b46e02e7527ac77b712b31785ef66da524bd680097d1e4bf448951968d83817ba6ac22e08f337032944b070e0de17d58e0ce99a55bc758f43bf743b1e978bbacfffd698d85c356481cbd10c272dd6ee2dfca53913afb41e0b5eacb693abeb5f10f6d9f4475a73184d208698e7d89d7623466ef4ab8332b753a4419fb459e29b67f392d008a2b64b97fdc17ebd81af4b54f5aba6e9b66583267472dde96f20e5767d25fe0954a2ee9df8f6d71fe8d31efc6d0321efb677c2bcc9efac39f517c66660b0d616ff28bed9ceefffb72c6222eab8f8b85788422e0d450c1f8fc81478a6ae1523ab9c5002e0d46d83480d7885c43c990aaee60b1697ca9153fa1ea89fd1655c5bb7efbc097f1323b3d9373be36842bae4dfd30a215ca0386520b6fe10c18dcaca30e22048775434d95436d37d58bd521f7ab1ca8179744f236af8db5c49efe51e54bad9d254533d086b31c2752d1ba51ac37478728e22051a70ab190b860049d379a2a605f36bdfefcdd7349fb8a84a1ddb132af28f87f17a01d32ca508c1384537c79a6dc538e1c412bfdac18a556f630de3858d292a89a0bbfbf179ad4403f746a62d02707ae7f4570cb3a40b065b987a3d92d3d8327b1230dfc0b1263d66ee896a58feb52e96cb87565c9a1d5185f907ff852bffad7adfac" - } - ] -} \ No newline at end of file diff --git a/Tests/_CryptoExtrasVectors/mldsa_nist_keygen_87_tests.json b/Tests/_CryptoExtrasVectors/mldsa_nist_keygen_87_tests.json deleted file mode 100644 index 7842d0537..000000000 --- a/Tests/_CryptoExtrasVectors/mldsa_nist_keygen_87_tests.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "testVectors": [ - { - "seed": "19e9e5efe0c1549ddb1d72213636d16fe2faeb2428257004ae464094ca536a66", - "pub": "862a80dc82eff6cea6a8964febdb42d41a33e2fcefbb5042bca0c90603373281443878eb4167a46b29b8b97a1c29c83895c7706c95ed7df28407054f8c682c21122d5ee680b3d2c481b9ca60913af0e92d76584a7a8e4642655f447ce9247b0b41e207139203e7a5f8d5821fbd59d865fc91e30fe3ddc54ef5dbd11e4097277a8a2a6e612c41db13e10913d88c18e5359039f8a12a86bf37036879f03c2c37110ce128c7a5bd95b99310b5907395f7fbcab8171f22a944b0a7b52e3e55f5142e5b0a4cd6b3a603597fb1b38396039909568cbb2ca3f867a47309bddd2f3b0b252d88fa1d19bc5f4bc86e497286b53af4005dcfbab35be1433ffc68fb12ec13a46ee1f7ca09f543e063a151f3a64f02ca7e838c07835a3ca18a8d50b6a17e36d4cec80a99e3871e2daf437435611e4095a52ee0e2546b20ed00a590baa058c367771839359c7bdfc75f1db5f661da87cbe02441f0ef8c85d6ef5032a33995ff9163c6dbd22d69eb4f35b373a0689ab354f97739c0e7ad9a06facf3c10267870e5788cf70a3f61e9c0e8d054db9864f20e778ee65d417a175b6cc5c0a2e4fd70e5583d09b14d93c364eccf357feca398bfb84e3b50d5c98a678a8b2e718c836a92c01db091a855f0206d08f3cb233f984ec459f2a36fd4aa4dfe9665c97344cb4dabb2323a2ffc5690a29bf628295cec833c298640305798c3c1528bf59083309629e1f0845a61a22a3aa529a5fa38197e58e8ec57c1c5123578f121f2256d67f6068a2bfaa658d731313e452638c8f14316763ef305d4e7547af06e2991628fb71003ad77f36f4a1f7a3a166bd1959b87d17284cc088a5bca8dc518052e799b89d54b953495a5c691f1e4c9ae443e6301f2d0adaef183a0f960ad863a3202d64fcc0a318c270033d04142e41fe8d49fb33b8aa1ee71a6ac80e0bef6c1c71026c18238bf86f6a9815af6030fd52d2446c93e9713f5693d912e427376530beec1a92e39952c22d6cee8dc74584e7d062fdaff28b5f68a3ccfc29f6fe8385a3e7ef863148d70b4f8c2adc3a2c32ff685487f48c6e2783d82b95496b42033717cccc1f42e93ce59f2c69942320191021ef7f9da7df8a2968c15a149e19cf6f293521b25d0088f2ad62df8a6c0eb7c799ec84dcec1b4ad617a8c35d01f14687a9299db223165ac238d35562793de5ce005483c7e676f9b178d92ed63e38ceb1fcfbb156897be49789b882ab532bf160d5c0f2d4390ca329934809773ce0f03e80998c1feca771eb4bebc22bc9ecbcf0722ee99eb5bc888511e513ed0bba566ac931cc93c4990595793221ed1aa552059321932603e072d2bcff47a7de572013a8e0f7d32ac87182dabf6235bdf88a1326d85b9f025f6c191d092d7794b8f5c207511e18d8d01cad19a3f63f6ab82dc36a3da51653b01b36a946049b369479a1f50927039bbe24be6fd06e212bf960251e67404a93b1caf5d9b343630dee7fd872ef6e4d1cc1c65a044c0e91bd98fbcec36b6e570a47dbb7a0aa3e9a586f8d12876fe24fa5a8fc97af5adf61a0efd0da5f53eba6168968b94c408a998819289b19b96032ef643df3b3e69f1f055c31ab172a9d7b92329ff56ab0bdcc60620d3fcc5d8aa5900e060f459f8423ca028937e72d4210fbffdc08c25ff844e22cc651fe528aeea12fc34c48c599b495064b546b720632baf8a29ab532c5d9d85a37fa8e48858ffe70e0f66d7e7078fa02f02b312601f40c73bea8aaaf75729df50bea269a1566fb133127f7e154eb703fd70b069e9b1d7094d17a29f76d42006ffd47f8747ef1c416cb6b503c93dbccf77c8717f20eaa5e196c4c718cdad8a39ae052f0e1f14cb64e2803491d2dcca8bd0a1e29e2b9e7c6abc8d6bb201185e50184aef8e264e327703bf5a14ebc11b63e95b84abcf466315729df3ee2ad569d934a0994702dcfa2feeff868ade0b6a4638434b1232e0eceb6f9af00f654e3d7931a7757f10e173d82955c8606e3f6027d182e316c0038293ab417484d2236bd6a417e48ba445ca9c106d52c3f97deafd3a5ecb719dd64b2345dbb9a5905b0a343daeb5e48c264cbb820e548acee9eccd9588e97578baf0ddc73deb6380225e68b814f20e57b1c7e75cd85746cc7891018f83180be697264d2d085ec7ee72205ee58fd9913ad805a6659c43c547bce51ba58a7e7720ecaae9b54c3f10000cbfa0e233852b76a31b04fc2b22c4112ad4e17e8a23be92c3a226185f604837f1c4679a6e1536a12a79a6d48d9bea00482ada463ba1aefd0f8d6dc580f84b370ed0e7f9cd59feb0a68d80328000c5f9f414b110451df834993a9c283e9a179238839169bc21f00a0ccd36c01d132772d46825598302f44c59bda2b51bf77c6c054c8fb8bf85ccf5a6b058aaeeba6457dfff8059d0bc00ca01f9599ce90d2537911f169d4fa3ef6fea617de7dea52b11dbc1d4ac803f6fbc133c83939db1c7c6c2305863232368305d2473a167dfacc8f8dc63d0a1c2787fe67cf5323924e70c2f84759f76a7138b4fe6cd4f53da865be7a3055e4c12dd775d85dc76b99ab38c21343b3dd37f7f9f157d83a3fb171fe29f863fbb36944fb93b0a9ce23edf7370ca3327fa473b5481266ec0d404380e6cbe800637ab0c8cd9f9b73efda41e1a7b0873ba314b95762ec3debc9b549ac9901d5c5448779647da29de32f7347d2167226c02063cffde1921ba509f91bd92ff9e1116e42cdf7acd301b836265d98b0d010b3bfb9a691332e359a804d288edf856d14de4116fcc9fe55eba7d04f33cf4a1653adcf1b7d2df562d7c69ed0e493c83956b235862dc1299b7cb8f8e722fbf2c5cffffc0bdd8cf63faa120802e5d4ab6ecca571cd5435fd3f0975e6f88b50b0839bb757c139fbf537363332872a90708e7bb86d3e9f98653e0a8730f0ae22288a128cb9e1cf1c821fa4ab5a4ee2a9b5a4a08b05cf76a8cf7130f56f40947be6bc40772d277a6da37e729cce932f9acda324cea95959519b5c124c3401d3a8b1d2badc3d287b4e25e503c36b1947f945b4f6e60ad2fe906396b85a32744de4c9621a429d6fdf0a43d8f957a5f8df50c66a0dea7ef3ef650810fc809524cc03bb8e9c2b372d0a63b821953a8866608df5b2d3324a62343646ff84d92819faa910e38ff75fcf565f21058af46becc71fce43a28f3752d4552be3efa9ee356f236b41ea689b9bf9acf8e1f8dc8b753a6b522457aded997ed80d5bb6e0e729ca36dc2756b13c53f105d2a004e785a19425b1ec855c9dd2a3f54025b7a526a25dc11c10928e486596ef41fd023d5d8a02118099c95f4a8b5f35904cd94a1f1d9432004a40d2328aafba4a8079ad518b1edc23bde45c1d5b0ac6d6ef86bb0a94e61ecab194a7cd14947693c564b495f64a6bf4579c4f083e42bdd66042e2c0a1a3676fb75c57d7140ad9cd155c35a7ac70e26ecc52ad5a41883e751af6326bb23eb5b90484d6c60bf619678d8c85a690f0aeb24302f927518c392ca38cf894d35d2bb721c9b7951fe26f5cf2d5890b0547b472a6ce5eda12ccef18e19e6e1f9ca36eccfc8c2ae3a2101d573df119231f3d5352b9794eeab14507a20447961c9025f53457d6e801f6e1bc34393d062f35e43d2134db0e08aa26bc1ae7d29da240c7d68610ad7882ffb2b5035", - "priv": "862a80dc82eff6cea6a8964febdb42d41a33e2fcefbb5042bca0c90603373281a8fcf131a3cd25645e9425fa2bb674eb2dbb0043ab07b67a30684d8e60c71e88046f4c842dc8cf0deb2bcd4d4488f4742502bf444cc0630d88f303a5c03f8be798922d8961b8e255fbf9eb78a994bc0b7a6ec480db08eac4e9dedab580af2cac00128504b4008a1691d4348d6186644a1621e44605012466a0260c21a42d018928c3c04521428c433690194246cc0604d9a6111ca045040326820881e114090cb00c482622188925a3002422430281c26454b4054246811b49246094304ca04880060a42b02c51b4205234610087680b2726d090880ab944e0985084268554220aa040120a8001232945238825008260e1004d1ba2888ab86514144c421231d21004dc38460ca28008a7009c803120224220050cc2b031d0464224364620938803262c13b7304c0689a3382a04a549d32401a00291cca8851a248601a965809268c308640b824d02b8080119651cc32c42262808989013084cd3424c49106ecb38314ac050db9485cbb2240c394a13092413a92149420ee340064a224dc8c629cca08484268183084061024cd21469434445e3902148243280a43119862cd32040923088432052cc1872882690423406c48228d3c47023b3104ba08520946de0268da2100162c8488b028611a150a0284e80c210a434280c90419bc04d0ab36563a6618308810047694bb42802252d1834110cc729d84270d08081e0c640623810d04060e0188e93c040d2320883a64159224c64c0110101444b428613965120278011483252a20cc1b60da1821041440181840811342c0ba025d1266110230a1c465084408ce11885a1120214246621a6495b1091538248e2388084040213c745a4348ec818251988315a1050c3344c0013691c058820448c92001183460d4a02019890500922861c098d1a9768039030da4488d446686296855c98814ba68103a50d911222a19084c4182c248600d34800c830224c328204272a98c03153446e1a002e81147213c961123286532431e19025233304da147013348c22226642268ea0322914898113985112426c11038adc48915c868d81b00511c4104a8680543229da4266da266e23844c0837060a952d8c942c58203254000014014e42c811d2c80cc12091a1048420176614300ed9c409d4a27022438cd1304e6114219b0200d8384acca64d5a1444a12272ccc088da40060ac91152386c60c6684cb820e2242661a20924096864b28da4b849e43220598448110520daa680248531428470222630203021d808300c44621c250510954082140e80268e10025284a6001b882c1b400493a0840c068d19356191b26d0205894c8628a24805c3863058166a43028ca1b28521370614b968e11265d48030d0064683084d44a2291c18492049001cc9302344448a84881c20518c2872d8063119a181a23860134092caa08dc8180a8242821a814022080dd1824d1cc66d0b836083924d02294212a369913430084649d0028059448ac2a6810ac13161c46451262001328599b800d1367063885044980524c14903344e48046d842690dc2485111749992400ca164150240118926918c2498920489a364d91082644444aa3920c1a33290b470d08460d1b396c22840d9a386954c2648990040182900086254ba861984451812486d922509122421b206a8cc400cb927103458111a31100400e510451c9a06552a4459100312404620c41001c4601db366121b11018b10c599068a29060d000100c0450e44048da946c0a09488bb8089ca84811a48014a56451a8708a2846c44682d242818b386424400593124d9cc4291b478a81b22802c405881409019288222860228549d0188ee4866c53b65112090094088ae010829a261209294d14484ad41604524810113902213565a4165110868483286d619828d0048283380404302a12328049800888c08421b5698b960003395003872c0334055434881b2241d3828460902d64b04809b51008158edc48624c2828a41892c3a4480c9924d2b0910b3021001442d1a06019a448dcb06488b2258a000461a22458448e22b369a39841e0966403082c6410099a108c99289110452184b4042240322395659016890cb484113480209245592830a38280231404d4428153c0510b98704a040c1a134d844609894261204d7176c8dd3168ff828909d2083ee0ebc08f4718cb1a2c262e26843608a07ee2545ae83c13d5a97ed71b236acc0cdac03b0d0785be1a274af43162a803a45e08ae6074c5f7bb5a1464bcc5e8983f8e6b640a86df012bffece283bb570926fae505dc2be87f5182c4ee95f0ea976c1977022957994eac2404a0ea84551339eb9a477003af03c06f439fc0cc4eda01cab80296d051d6b5cc72ce1fa342fe5f466e0e1e09e8c90b45eb6268e4dd72f0a025a8dd4ae71459557e5d8aadc4949370eb64d792d36300da2049c7af9f6487e5b41fd73154c41b4fa49eb56fa4467c59c9c4abdf610774b54060a85bf237f076777bcadb54a90f10fafbe3a408ca8e2b7bc1be8208df2eded605b1ae6bb7f419df9edfdd9fcd21c3d4064e772246690c745990e4707e2af57772ba0b17ef17a7812c197df3933c6c3227835a5bfbc9380af0fa35e6666ccfb8f27be6b9d1e6b4fa85b5abb4a089544797cf762fa687ceca6fde5991fbe3359eece4526dc7473dd2f009fdd6e92cadf0be156901220df11564b312d3f9f44f810370ca45ab29220c22ac9eac1ebb6dad3042fbb7fb463e2f667de68d3934fc6ba0a1b9ef3d458129d62742d451d827538d8b1e8faf86585c10e64aca770d4c3de869c23bc033ae132f42f57740450bfd96e00b5560310a7fd7209bc701497232d4a3a0ed4d775e0f5a773932a029c8178c9ff1924fff38498ba11f00ff80c1f11c952f2885141258b8cddee490cb72d469f9a584eb08107f2ce218902c6ba35c31490789e6cd90178f46e2ac9ad6dcd298f555459d7ae82fa3cdee1ef07015b1a1428bca33fdf7c58c232bd52985e8b9bb0ed4188dc6696398a4c5a744adbdbef4a50c9bacf41439465439b6726e2416efdaf258cb76b3ac0ff437e5daa90d77bcb646d2ece30907ee02820f6dcd44a77ffccf5d8bf4bbfb2100b06da41211598bb6825c7a4ac4cf91005f5c9a36c24162498a8ccd012069ec30736ffbf07d1f501190978ffc7b8ac3b66a43cb16692419656f03ce0bdb2c278096b466f40ab371043193388b262b5e4e0ead301dc818033117ead588a110af7f4067ea702361f85e415ffcad313648f4d8667cb0e79313134eb3d3ba8c9ef87871bdd11426684a36d88e7433cf88d61b80a09e3dbd17bf06457c08ecc0f030e1d4c5bb321a8dcf44902cb22d72051b0c76b3868a8e32d29a9ef19e2126185e50647932359d623ec9112a93a748a31abd88db58f5db1dcedf1457344aad3d3fd4b04bcf5fe0dad8d4f4569c717456c4a5b9f94a495f725b0290016fcdcf770fb6bb94243cc50ec2591b3cc919a4f2303c8de9e05b6a04b8a8cd49422ab980c7f7324041a8de6a86e599fb29def0c60e3ce799759ea81ad3b3b716ddf21a388fa6c2f4d4bdfdd45cb2fea08b56676044e9e2a2d10d2726ee6af4e43fbf0c77e4c6d85f6b2614834cf16f1f0d812e048e274494558de86df4594107924e78a439b34e0715736870dc8a39f5cfb1ffd19684ac22973f3d46ec41c4fff7c5b5b7bcd80f35a2ec92c0a5657906b0ec23ab45fbe3d5ac0118341297832c510952793c68a9bba7af4a57a02c363425f9ce1bc73fe985efcf385366315494e4b206dc19c891b1d7e6c020f07e439786f2ae0f6c6b5ba64a1b592fd53f9df22cebdc184dead099b411ca5bfd9ab839cdb276dc6ff2f73b0fb5673637805f06d8246dbfd6f3909f0abf5c30c4553b6a62bc2538adcd48e508a371f35410d199cf8bd474d8f21313840e8a928f8be88c3a87d660eb26cd30efb67c48eeded088bde6e4b52b1debce5a79ba257bbc20ac868d32dc0febeb91f90a15f5a98974e998dc23ebc0c43d41f9c8734221429122df32255d2ef34a2301e1c2589c1f3a71e18a318f1013552f2090dca49b8cf13db45222bd3ba7cb21d2ce00008422a9bf176d5bbd29407df9501518dac3d708fdeda67839620ce20fd1c3eae333b173400aa1bb083ddebd7097a613fdcc0f017d6f5d40d5c8d9fa379630bbd84ddd0c836b5b363ebaa435057200dbb73a3ee92c364685638e6b60ebc432d7be0485d6d33e4ca1f2c0c5018d68ed3a59e1e32874b286bc01292a8df1660cae54504b18b04fa9bb4b18251098cd6bf81f273fb653b48e42655d85447730a3b4aaaf42f72d5107f843c15039166d48b70f64a9f8d626396b41a14d07dd3c1b53062d25ffdfddff53c51a4eb36872577a1582543f8a31eef247054f345200335aa7013a6b4ae4f8dd28c683fa01fa85b0ac83e52aa9f6f0a0f4a9949759fe9027d2b4de192e8b5023d0e232c550fc0992efd9a78c4465a132cd73cbc34ce7e3effe3a6027de8f51fc9264cbb9944bde49a47931637af23059fa9b91edeeff5adc38fc60723d66c34cd117f7a51e5f4aab3f5c6e86c47acc1f6c5109c861216703399d73b20eee252a8026ce88629f35a5e342ea33467829de482fb9d9a2e3c4205c0ec5e14278ac5199fbfe13e604c48265365e891d2ef09ac75de3ac39a328caee0ccb18720532c6a19141c6b72743deb428d22c476c276847da73b2672e158c2df3143b4790e96ccc1db71b0bcbb5740d7aac942bf70f0e3d72fc3f0d6f5b85c3fc7731c7b4ce3040677eadb9aa8d7ed862948f715b56a59e539bc6daf3732500ae6fe5ffa854276d5aa4824810f0cc7711aa731cf9443e27791b76ac77bd90590f7558a9c63e70210333ca559e25165781f2b1a9e52747495adb711ade7cc6c4f2ac1213622b02c473360d4220e194772f36d14aed07835d696f8b9b04ad9cbd3c017b129bbc2729ec351828b18658b04d757027c4c00668ceaf9153fcd9972d06ae3dd09c0874f20a69d1929f1f69a3750f0cd71a9eeb716d74c234a9f3767f13a5f3eb39a701ccc26daedd3529e6957c9a50e1adda96f67b29ced03f3ea45b35ad5e850ed51bcb5978cc4d7fbe90b625766dfe6ba205f6ab1deaab76a304454b31f74732b541d366f177b8a403adc131068faeb20ffc5ce0dedb4fe12e163e351c3468b2141496ea913fd86a51e6e1d402910d3e8bcbe80c75d5a8fae43e5e473ff4d00ea624f6306d32c41d5e17683b9eb07cca5b928942b03ad751f71feb1562e06c3ed2295acdcadc11d97881748b281936a89d69ba85afdc5d39d93b007267f85e693a25f4dc275431582635b4bd2de0b90a0a3084535fbb7d3798a92c1e163fe820e825e9a4a501acaa57ed77e6d25af86c4abe15abc0b4c47ba05c6318b5e47a855f8ac51fabea0ace83e4b0a29e55025d98752314acaac2eeb4ac4a6ee1e419c3e1ba11f08fcc2eb90e7b972f38124cb1645525580f6672fe386f916b08e065590f3d6504287658e71c62ce05febcf1279ad624fe1b09041d78301fcd77c213e0fb63cba2d8e61721c95ad90173ef5ffb340f467450370edf0add418331d0057f60a1b3a090821c54bedb29d30f1a63d015ba6bef6c811f79157323e943de64ad16d290398e0670c471f9f2c880e364d72a9263129f61163a0cd25f273484dcc69edad9823d423d9c3f58774f014bd8db0bfe1de4f3c715dfe9ea09579f89c9bc93f4aa9402daa12befa2370578d945724227b2e780e9ec23446e08f453ae5b81d26ea85e013756b3f513141c7430cf5ded415c38f65fd2bdc506f9a280e92d9333bb4b4c938ea4a6c1d118653491e56b99a648a46310cdef48c9487d2b74f9430f3d242414ddbba38c6cd207498856fd30c54942a928863e3125182ccb24f0279e8fd100fb752b8b52e8b1ae27a4a028b93c467477feb80cfb258b7c6b965d3839f24e0198b96e7c5a3b5e6d6570b9d28b6c9d028f96b8338599aa56d48dcb0ee832246194e168a798b9cefa95d315f4888ab4159615ff634d82459393c75db97179bc95c55cb2dc277f82beb1a252059286e1c7366a6e79982c345f96b2b95b8d7a22b3ab2d805877fd8670347f002d47f2b6c7d3019fa5aaffe9a50d64a1db5b17d3a41d75db896ca91a0ea517bbb9ffa2988ef5639f36021046a3e98f873e94ea67fbf64f80a4fa3e67d7aebcfb1d33929fc97ee190ad754793d2ec6754ae748938ea1794496df81692391ce55578a4f461deb3ddc0977b4b362f8a8c9c79abe307548ccaa80e550d55b2759c11bbbafc54f06fbdc1b039d8334c1f7cf49cc90b6b8255339731ac21197407718f477474a1540e77fc72372da470900672e6ee2d7c1813dc2e559706ad8c05c74673dc6cc007ddc2bc6740924e5af1736c38f21038a8b19a0802ba520dc354979c5cd6f99356a2ce12c86a6d63ca40b25dd0c210f0ed09448b2314cd2eba5085674e4650c590c422a891375cc6add5d791e2a457693ca0382c91bc9513b6201f4c7a750228f8a3e648d45c891fe89fd301780bcc1492170d8e50af8ac60c966b5876318c0deed1da37ca090fefc609fed3eafc0e585ea48bdc587e4c61c51b5f23594c091eb8da5d5585be90b83c1bd093984682f77530fd838e0e315e34411857691f4d34b4b6e4c6b662088c12d4832c5ef825d275ba0a4372384b02e7cba99127d754c196e5f48735868d4028ffac580995139840faebd7bc9ec1148751c52c53a085e856efeb5b41583bd40400506c5336a37b24d221260f6e85cdd1b471d9773d118fd0a7e5007952b382c6d14689f2dadc2b045229ec2e9d636f245105cd6084067babb79b643eea98d19910b3aa8c17f1" - }, - { - "seed": "151c30ef6d1531342066adf2784ccf51078a18d83f33328664ba37c12b8f5dcf", - "pub": "ad6bf7f602a82781791afdd5a98883f8dc816c12da2243f04b8c4e95250ad2288b5c3b419dc4b40f8efcf4423ce966886078b1e71325e09ada44f9a1a489fab2fbe3d176a455b48d5f9af10b706c88c2e60e5f492585e6fbc9794ef017ef557a687b39b793553a6f4aea4e17a5ed947d30e1c083408e363964e6e81777d6506e051755885b507f160c0befdf3ab791bab6512fe4b3520dd8d02fab23e92e628087cedb28255bd36cad8eb00a363ee059922cb6e2d5601294918a86d0fd4ebcf71e474982e1a211e52a5eb289d129f98fdc48dd3da4c2f8d834791b1ea6ca974037be7a3b67d598e428c676df73e496f1ed52fcae11aca86dccb5eed152e54a4452de7bfd582d374c9c93a4b406a5a289956f5719438d1203d7b42c765b8194f3727fd9606b45d788123b692b4542b13411be6d3c421e8ebfc34d298fa850a663e101f52a4c328f2272ea339e5a3944d24d627a7edf216a1d8dca2931ad7e741a68439a4a085becb857bcc0e6a21a8a610a822205ae3fcb152c4ce4e49c95eebd329207c7d71b644b376822c8d23bfb9da1ec14a5dd1b58c23cad8ddbb8cf2e237357b4d974a2a6b58e2e1074afe366dd6fe60c5c992c9bc78957b8f2b53cf504606ba89c88cfb5a4a42a282ba4f8743d6dfd206ee82e5efb85088e61ce0358e087854b60fefa98b5525f10cbf88314a61aecce1b7602a9c187c02fe736f53bdd9dbd7998d641ec08418d40e08e79c36a9050313f1fd4c0cc435054ebfe54e0397d4795faa26b93b7697db95a4a2fa5fb179af3b1b17082d8077c85f6ad151a1c625915b9adbce0f37628ee8fb56b97e5ceff674b1cf564f8c0a1ae24560ea42aed9c19bf8e3cdf09a7830e67a8bbb5e7b5219b63500ca13fbc2c58b92ad3d05c70cda28bc0ab18820ed94e7bcfc8740bb2b68d8ec2db3d0f1e395ed888734bbb8507523df73ef051431d79ebdebfacf3af0feb0937b57fae225ed4d71078e8938c766fdaa433e3acdd976c4ed7a9e9ad3d71dae0b50ab54aae2395b1fa2ca189d8eae247d22c40c9509d93e293c5066890f7ce2a195b345016c5bb602bdd402951dd155cb3f9831c38af1b3093f6f6648b341001051a4ae23b95e3b2eac0caf45d4a934200767c16461efec684c0914cddecc34be2f195f063f94e0e8b9169208ac457692ad9170df02f50a753d2dc8e7a508a575afd47dea6a61b94202af7a084aa2ddc7bd52607a75097fae5272dc963dbc2878ab07f690349d6ea1669cf1475f5ac10caffc313cd384f5950a9536776c0288b49e7a0b880dd046633a8848bca17a7049688c4d3f4e37d67d45bc23de7e28342311031ee7ef6c279d69f74343f4fd75c78293ddb95c3179f0307421ae204b2e393bf52c38a76a2b174247738f443dae1f0890b407f679c52b5e1f64331cf476a30c9516384261b7f341eefae6bda0fee6c15fb5d98f43befa87ee6dcbaa162eae47aee040aec7034c9bfde769c6bf739dadc30c8e284a6f85a42dbdd4af4845418d95f9fc5e1afae2aa1a554619f9a8238fc131273a14d6e4475860e0f88f9a73a23750a7c20391486afd9e5d9679a5af003c1f93c8bb16068d3c66b2d91027be450f522589adb79faec0351e70abcc8a663c85c0d1efd15ba8009727561215e087e7cb14852f7dfe9a4f4136e5e2a8f65c57318ba30a9a6a7021cd8bacb1234668188dbfaf8dcb74c9a5fefe826064e6c025cab7857e4671a5e1a2d931736237c5e1a747ba469a005de3467573edc656cf66c8e1d173d0cf19661d888ea4bbabe6b2e87646d2ef049f050fbe22c05c4b6e51b45592896b6ca0eb41216d2b7c92751f9d4bed6b779817ff9114695bf0c0ecbb42546ab3947460af90320c8f584c90726c9f4393a940f2911e9d7f48644313688a3dbd620efc1ac4e4ba4b7797a31679497b1e104099b4744a53ac548cca28a1b14e2ab8627c7c912a03c77d593b8a998a06070068910a515663195df633f14532a6888d316ab2c00bfddf63662a0147501f77b4a2cd785b7715b576d4934efea8ff11dfdb261c4bcf5edd9e41f0c0fbd73b06a695ed33232a68c95ced173311f270df0d5eb8fffae5b1cd2b3e0c58f7d4745c57b8ca7a639b66ac71bca6775b618985d0768493b8137bb0ccd973065ed05f59930ffae52528755b09b1bfd562de4577c2b996280213429fc31c131320b322dea8d11014721bc136c04f237bd5524c7d902c349c69264ecafde4d6d567a94b0df4fe3784de7e7bfafe11f4aa52f5c8d53e16e3ce3063fae1be64f0f5f90d83d3e425463e8cc0aad7dd8d03586c09ad904c77e18c93faa3acef6545185e5e701cbb84caf494560b6f2f7951feb497c52ab41bf408f4cb0f35124e57f28c67999cbd99252953ec132623cfa783e108fb6edda83f580f7b3e894c20d33ffe4430e434e465adc4b33b1064c864a2f100cb3b09076185e0f65f3ffa9e77a011097d5bb478e409e6a5f42466cce2b96f534e82fe5f715342412ddbd0af5c61985ec52300bc9fc3e3a541be522e6d14ddfc1a72f200a50fbffc099576208bb6922481a070902ad69d8877c3c010e0994006fde90ba16e691c72da0bb13c21d067766292564546f831c1fb84eceb74051a6d418db03b40511275822d5a30f43a74768c7ac475c54abae3eb3cfdee5f6d5b1bb1974f5fb2fcf9aba287991970588010cfb70a0c1d742ce2982590d5afc7f434f3369bdb8f0bf3fe0b7b858c0e649af573cb0bd25b646d16e5ef1fae69b6ac1a7de49c249cceb15bf50020728bdc9aba59d11f78a01935fbb8319a3c04fe6451c45f477504605cc90d0659bef076011564eb221e883c352fdde5eb57969f226b533d71823ae4edc3d3d7c1aa21835d8f90f713be45a90c982ab5f265c53ecad2b12e9d94c93d822e3f3c7159c4d7f2aa05a0dd0563f557adc4c96ab257411c15e00830053da500b442c9c4537f23ad27ee9835bc2f723ba8485e0aff118363580c461c92d010e97dfc8c28d987b5daf5a2d7f31904ff42253b8742f7c43593d2922e004878a524825eacf19bfd8b9f1c0a327463c032d43732a2662e6626bc28979356ea6a3cfdf0d089c773474ce49e5299ddf39281975c87e487ff3d8b99f7473e1b0ef378b02f52e5744a6ffc75fdf2c98f7d0e284242c3c83989009c2f9acecff2e0ad567cc553870638a8e7e39e1b2da18a7adc95d3bb1c9208b1f74d8faf49d9e50c37157feb292d99bb8c40f491ceb857793a8e7f41f048cbab829a7b32cc71bd7ccfc6c55446f7b6b1644e802620df4b26b4355dc1986b5f3d33996e58e2a417b1e5fe9598d3b8efcdfbb709a0215abb2cdb9f363552d802ef538ce8d32971ec6c866e077859287a66e6a002642284c4e8578173bb9f1d61c3b53bfd66738930656d9fe838141663faf70b7c74840a91288bda57e3306a65574606a64906ae40394c4b6ef3d48d04450542793829719377aa151b27c4a5e9e2bd2eae859c6dc2ff766fb5b611b9a384d8d5e35db0ff927049a5c7f632e0b88edcb25404d674c1863bfad1defccb298933016ab93d421e0c064c6ba0946dc01325efe34e019cd0ef2ca00d57db75996f4efa2fabeb866a53abc148a8993322b65d91d4268800b69908348485626b9527a8c20a692d3b0e404bcdefa", - "priv": "ad6bf7f602a82781791afdd5a98883f8dc816c12da2243f04b8c4e95250ad22853dce061875720aab2649bab05b31eb148d35a240052941bf958e7a8b3d3a0c59cdc3a2b790edaddaca11347df349b78c19b1842fa18d87cea0537a895765d479868b8fbc1c88517edc64ccf1749011a83fea2265ca6928ba5eb28442300f3886406211227209a12201ab26dd89650d1b47042a284d34050cc0202c4022418196520372e1bb35108244ad4948d5c00018cb60dd8b68853b46090c4718928889122124b14919b320edb206e63267148228013a10c5330098c062c18b0500001021c9425c9808020989022244ee41609044345d38664a404506322499c9225e3c6212221929892281a40918498911a302863c008e2068402a17098322cd90402129110e3484c60108080348584266d0b3588019480c2a09011b96061240283184cc082001c918c02374214384ce2b0084b044d044090c8a8240c812942a824238569520421ca0651e1a8801146881c432d0b289109044d01b290492648212712c9a88563a42de0048652a068194710032210e1208c53148d03381040c248521881c2868150344c039568d3a0880c0890141605c8b46498c05101a924a34469dc303112080123374200214a0b290aa448668b144211426d0bb2311bb369db282004a56cd3c84c5bc04559067119a36109478243c82d1aa9400b460e0907604b8444430884a4206112a26199002502163024b86dc8489003944d52226d81a20d082992022992030412caa44cc2440d640270199901002068c1426a4a341218c80c42260220c751981820cb9209030168cc000a4b068810c06860a48064804c04a368113472cb2689d1428a9b364509252551846d0bb16113030d4cb0859b228461a0019c2291dc007024444e11455199184824b31048b824900804c440005a4205cc428e5a882d84b84c1c264a0b38860b122520c780020171e290010a304cc3166809259202245089b42de1466903222850a84d14c8840b4609898264202461e3300e48206d5a30800c2385dba48c9b3450233248c8906ddc422a83228ccc9091a4a64913932ca2888c04c82c54c68d2281699a4032c848060323088a20101cc01001216c02142191840882327242920122138c93a4850a23061419014014309998304c101093c84551022210c10d9aa2280b196d40b23058c49113224120b32140968199320500446599224a09138611232598c89041a269c006020c492460a890e1462e24854c52240d90126654020c10b745908088c0082620a96d03a4289bc000c4325011914d22484442222954a68c41286822b86de286402190811920684992305920610a916d62426a841872d346094c468ec492715044851119220020608b944d0a2602242002144472a44624c9106a1b368102c1505424521a4869da040984c2306330128816700ac5646244281998704c1692a0202112994c88028809208610c08813412210384908474c139961d404845c98081b346e98885114b30558b8811b406421188a5896891215924282418b946522032a60008503076501896140c200584469239231a3a07010c38042a40d422080228169e1b06c99486e2142864c0648c436658cb8644a04625316491c83281b81610c9228c8a22d588644c40065083472183730cac084a2c401242545903804d9b0259a062a1c986c21830903066c51100861068e09947123911064b0602100898ba48dc4000044b031e2300c4894651000864a2232c08441924880203931d1180aa334465cb68ccbc66013c671c4a211d8b46520b34513456094c8295b3252d02491e0b20921304a40c891e4a421e4c830cc1631cbc84911380103095109084dc4342c11194108458204b40d232491e394681936528cc40154320aa4809024490a14a14dd2062c12b94193884d49202d60424980c6245c2086d910648a1085113391c0284a9bc245a04662584406e4166a1a918413920843142c90128c12b10d21b54cda428941866102026ee00622482492623842138520d344284c0466d0222811b92c00350a24130003332a4b860c94b6491282815816861c27411ab908d4802c83c44dc2c0101804685cb48c4900690ca44c430600444226e3087002a740d0926d5bc088d3244d032506490281d3c01193809002b729d896408a086c94306c61344a00a889d4c020359317da8ef5629dfcdb9d1ee21c68252eaa60ac422b39d1b83c0f9462a90895af1546e99e87ca137e057780b0bb3b9696db70f41f7573fa7dee5125f6fb891b5d3d9f707fe18ec3c52cdadcad3489577f9e4e7447ea8696c3b7ab4d88c8120123b8aa87c6339dee78808bc4bd44f42a7709b6f4a014972ff5e843824c17904407b2cbecb1a4ae0fb359ff96574202895dc8f02888e036d0747fd52a2cdcc7c9c98781a9c1f9efa33cdf74b85fdac6146fb23491a958e6507a2b89e72cbc0ed5e077e3af972290917e09e6d6c5f210c075090e4586e65d40e6abae8802b87fa088a6044e84bcc8d3fe2f6b8a613cfdf27306f1ca13c0f12b27a481c38d6885d02ca8758d05db75cc1561d9966d66dbc6da3ffa4176177915d30e7aae8ca6a63a071e592fa88bb1d335588d8342e9a950b9b5b6396cab09dd0d0bc99aa1c9e26a0c52d2b148c511c98eeda015dc0f0ceb8126738155f46eb7ace60fb2f970f926abf03f4cb342eec87846ac989b8bc536bf0688e9df9449fd8211ac6c815359bb880f58ec53245ee5a80a785e65f47ab1e37c93d83e330bf8929f6ee7a2f8371032eb3773eb2def87b1a20903a4f16dbe5f6b916c6912059a4cc57a64e7bf45c7526b92fe556714cc99f7daa7f264427b4403a50df157a68c5bfd0f5b0d956c0a205fd3a8ec696d0a8b8eb2b94d41a7c35e2d2b7ef5ac0bfbe2c0d80b16f95f4eb207d071ceeee63ba77c37c34de5e0476fc521b8ccaba0fb7220a9954c921f3ffaa9f1c0cffcf7eff5ddf06cd6f73dc9dd093770441e4caf69c1fd1304298a158d1964863aee9be257116fb21669856316b56ad24be830f8eef3ee0a1846023af42523b02611d5461c8674eac4e781686de5ee58ac1371008ef0bfa6e22093ddb5f41615c25ed6d6dcca2950af2b6895ec8f78824c3f9e8e495ae8e071cc78941b9f79ec948bb38258c19c9b7d885b21e87e18a964527fcd689608d31888ce92986ad1680de8cbd024a193f5d8514b9f91475df6e77af2222d2fcb865d423e86e20058e479f6107b757a62a12b16cf4c1e3ff06835ccb3a21f87ae39236aa05330c07a6f186ac7fa7fddce4fad578d8a9756d7779e6fc21d0891263ee5dd24004279491ec519a177cc7a58ff8da5d5fb03f447ef188ca400eb17f879c5da4a6e9ef4746d59d7439700605ba695f6552aaff024a12c24df3b9abb21c4b25b7f133706d5de33c8ec7953040b57ef2ab42374fbc0efbf5f61daf3003411f1e1cedb75e8cd30eda1b9c3f8adf9f8a24f0b40509b4fc42ebf037184ff9d4892e01c8c1c1bda0ed0757a97eed7024a0a1f01d513d8048fa68a917afd08fe1bb1a84db7672282a9e80b1c1b47c98b0befe5f9b872caa03a3c0ec385a16c1e1e0ac40ae9a1d2adcc7876b35dc137e89795a12ce05af42c887d91511021699f625d85a46ab317cc27aa6d4e50f5768743f976349a9be7394bfd93fb4059705bf7699a5bc21ddbee3c9d06d87c7694e776567727557a9605fb1c5e6a44f7ec55ccdda4e0c2a048e2c888f140c497d2878edf900b2eb556460d493173fa96bfb92ace6b2a799a86e10b1494ee133659be3049cde26e7bdda72d031fb2cf82522f7e9ae77aaa60757a68cd694dc5b62d24a91168e3c72ca9289dc587279e71338bc7e339c5e9d1931060bf8fc09773aacfeddaf93620d4c1e6828625140bcd435f8464efd134522dd3df189263a57dfb5054de3e45c84ab9ad78cffe37a9c5fe034d34f7fd3f57b92bfb86b1bdeedcdeac6132d707ec826725c50a6a8cdedd6f299d221debb4d3260bc5bc6197623c20739869a6a5654801f844f606b3218e44a36740d12627d6cbabce280226b1d29fc680653003629d79486ed71e16c8b3f525beb1f0cf5a6346881004111b599e66715802f89457ad5350b9426b54c2d0b2e5eed8ed4fd9935887e3f2c5d828ab486d089d9a28b3a96c792e5f0e70d44d7586bdb5557496a032094f88fc49438aff7b45b48faaee95b5c1a06f5f5540d7c427984d720c0c2c2ad924245a4c750d48fc9968c72f60bab7e9287be8ec72c590ecc8442e86d9cd541e9ba167c19bde73bff7e1cc049b368e471f9df5d33155966c4e1200704f1f3fa78e5c443ec63d888689fcf94c5f1f6563645045faedd503c7460dc7da02a62560244fcf67ef1554101fe7ee61b838a8d50946f0641f749b2e61dc4a129b1f0a19f5246c3e4aae23ced8d7e99761de9e9bc6e436d2b51cad11ea532c1918a8d9cde681f1d36fc3cd0913e6ab9b2979741a5750f17be4e3a62ba082ae254e8c164f27e9a2a9ae9f6ee5fb5ce0f039b58b7022fa18b81feed9c2000bdbed9fa5c9a3ed105183ad5943dab1ed369d923f295f1951d5a1e078f1a24b840615d8152a0f63c07c799292df9f4ec21ade55c75fd994ac86e3afa1c03f5a374fdd20956b1569e623cc6fe27866473e57db877493716db7ad70e009c35b9e49548f047ee857a92369d50b2dd38af01b24ee8bb8d18dd248e999705dd345c542c2d382f17628a30a9c4c8f146a61cebcfc363882176f4327f31887cf21bf29158d71585b2c027e6ad7dabaeec414273b3721735d36e559759087a34533ec907a9d81be5706e5700849acc357defd08ae9d3ed175e64df0d55f96d93e770cebc07358054adf412d62545dbc04c14f3d7bc8dd2f9f9c99d92ec8db89dab276144b2ee99ac152c60122f607fdfb4b3fadddb1725c00dcf1aa679992d2541a90018fe254bd4634bd36605fb6bda8437efb9cd9c3b5e5ec676400305d482036211be2b690b7ecc45d2bdb6e87fd44f2a9fca7d4ae15bca5fc3ce755c126f1e45cba3cb2d5752789fefc34815136d1b2867ff8689857deece44df1230f5c903ff29ee73466f6dc23e0abf74adc03a990b68c7f1d5b00db11ae49af6473a56693468dde272d76807f5b08ab07001a60792eb3cf863d236043d8ee6c0d600a63dea89219579f95160d954aa5594b9996b92d01249f1e7a1b870c281a935ca2fe4553c324af32328372a54f3b18cd3ccd4d3fdd13516286a69f3f8f2a0a16576403f75c979b9bd8f7e57812eab9b612ea5d74c1dfae7fc852304d248b3d9420a66cdf3c54bec98612d91b852462fba583f58ec6d5dac9c16e8143c15533fe3bfe8abe2d3955cd17a789215ea3f5813587566b50e403e8b1994730a887b15fbfe1e27833227ac4d97903d52ed39fb42b7404fb28dd9590c86bde24f9f3d42025bca7b616cc0af7db5668af99740e1e8776801f504d0548f6ae26e6d5325ab811fa7d7529e50085701e3667edc9d93c309acea9fb702ee3af17d02f3e41489bbdfe81960217a69a1c2cc48f577cf0134ee04df175cad9125d34ab2bd78fef2a54c9368a23a6cb17d2f0d3fc507b6c22d64954c9a7271d3f1419729344d25980ae0ee5c75985d68c2ff573733eb1e8987930625542ba901805577485b0473949e006f202b9f8e698c2983d7d4edb6dbe6210800383a60048c3316f0ee34c0c4bdeab6738a6397606c5309103619aa8ea107bfabdb616cb142fcb31394a86b5b8a046113b172bb9b8850f73da82ecb24d380d0c78f9a90edcdff0c0333288a0b01de0bf2d5be5f6477208c5f88fe710e0d883ec43b46aada5753aec4aa0d35fcb26a1c8ba7da456aba5972ebf5532be93a155caa70d635b115e9b4d5256904420c279ca33170ec2de71313921f7284a936299ec2cf236672a7a5a183e533f8704481d96d774dc037c8a9316d04ac7372f4b23c2f9de14d9305c5b250be53e8797e5e59ac03994854b2b580e8f9719d45b77f27accf1a3b546ebac89c9394e45d9e5f872d46778ca27918c44426e0d134db5dd922b0118e328150476b9da889eb814a47b08f1773076c704a936d389a290d4d5a996f40fdf92828907255421eca77a2be574e5672cc83d29fe4f4bfa788c2e93ba0fad0439aaced025a57caef35820ca50b2ae1a45f83b39e6df4670fddb1466a04efc19d4d8340246167bc399bf27be4ca17af82e4794c5cedeac132e07b650d4327b628aba01d094d77324e2507d1874d7e6fb9169a204bee4c4fc66af839dff13f3d1c73583cf2d7e85cf864fe39ebd4975413a3b023c63640285a4ef529d2fb5f89592395f7a9127279d495ba9c6a5f4f0a9197aa858e3af666f91ae72bf48d3f9d0964eab5babdf13ac089783dff42614e194e3d11865c00c4b0a9d0fb8c38fa868c9c883200f7bcc06f403c8a39b6f2c545ce187e3a375b4c26f7aff956d55f41c199e5f9f52b88ab01a355fc8c69f6fb29a24f453c1e87f0602870a593ff420c74cd8758c796cabd87e9deea1ed0ba6c3c6a3714b1d39b101c61a89a23c9ef97eac3aeb58a178bb6c2b65ac3355540ee8a28c0e072f9154d3dd459261f4df3964ed83ba469d4aa4e9504ab23ec01c3a54556e70e93b1dee22a2bbf6c4a40c46557438effbba8926d8edad3679c4eade296e57352dcf6f4fbb5cfc9059185510d05a82551d94b84edf7103eac5002ac88d92d1a9c86a9b34319d4187d6f3f54ab859f0c8ccb02645de3131019fe3ee226f8a56465e47f1b97c9df3147dd5cd2cfbbe3a4013f0e14bcbc423474c905902468d5b08600ea92190f74fab508e96e08ffbeed11d4caedd3888d3230082375b5b209cc6a6cdc8b5b84abd0bf4a9c6690405bc4fd647588bcf909ceb2c2e5c0ad5e58aff" - }, - { - "seed": "2e741e522ee5b0c202955172dcbc9afc6220f3af72df3c094007fd20b5bdfc34", - "pub": "4a9cc810d28cbd1a6aad332c2ca86a09de56dc729ad15f9f8cfd1a3a4048bd38f4046891e09f9051efa6317fb7febdedc0eb841295ab752fa99cec38a8a06ce5fabae7469d509902d1e4bea7c267cef05bc32813e137a57c039ad64feae7e11fcf154993760f6faf50973568fff449de7263e17353d2f7ec5e835f1fad011bf05a7e5714e8526dcd07a9e8261e414d62e2f2ba46849fc145cc9f0c67e4647eee24a00c27e9cb520c45327cd9713682296520bc428ac32ba4c21e1aa2fa8947295256e02ac5980ff376300d8f962308098115effaea83bba5f567fed1c1d68cce3bd164cd2b041a0ec1ada599c3d7be65528dc40521abe89909bed86fb55ae1b92858363f9bf52f5712e5982e1292d6ed8569e3e01946013a935ecf4400ce0fbed4a64218d617e79a51d8c853708cec5f0bc4546a5b93380987d2911798e27262cf481d44b61336e9bf3bd305ebb590c15a91732a2032a37b7bd9c8c5eb8b61c8ff157d07451ca1ec4ca87fcebdefee3c52cdfb9f990d57a2ff13415554ddfb200cde92a2dd2a94708abb9128a240348309866bb6569bbccfe03b06592b2f2d94948afe6b245d1c70ba2e9db6cd07ad40d8d794644e698ed702d9071afef98a9e542cfdbb06776747f2bf0abba36683e70c6345d3400f7343f63a307e9fb12a7f0aea6ccfffbe15bec5c865c21ce40c296edf4f0e7826e6db8f86ba1be25218d72a88f078c16f4b4be79e480e2110b6ca9ab2f863847072ef06fe52f4fa0f5c53ab22e0a2755d668e7e9777b67bd0f85f05335d46afdd3cb9f975ea3929e3f7d85a211def56fbf3c5b8d610b3bf58e4f6951579f829b16a5241a9aef306dd5481c4ae39363369052013703b192a484e1e9910e7538bd89c58c3961cc6a8baf617007b61280573e8a9f2a31876439f89c3670a02d6ebee364534197085b257c24ec5abc378c4762a12ca4b629eb34edb44c3cd9827fefc02641fd7cbe63356a8e0398a1533da693f6fc2c828570ea0572da48499c1625b9afb1ea7db893f01e72c286b35b9b9b9809989d3b454f3a374f80451357f490930460a34b9877a40507a0a22bf1c3df8a202369ca0878c98fcd5354b4b478d1567711fe45c0fff47329cdf76b1be075f7e88bd31fb76616aa56d6a3f7c3e746d46eca1bb94536d60e9980739657b274b1883904d46ec48f1d84cc474ba0a847b77bf9a70c6ca24568475140a0eb086673bb4e75aed5ceb862c10ea64f895b57c019c27d6f75668c1bdc1a60f008389298857f57b7c7c4009803e1ff31f81e55e2941f55c938039918851dd16e6a4e085d6e7eb359f82de6e5d37ac6a31696a88e5a3848a083883454b0035bf1ef050743a33c1d8cc89fb89ca804aa5e08bb9d217a7c0b065516f851a8aee1608cee8dd87ceca26b4a6d11280328b1112fd7c26a83a1dd35afa97aad1c9086d470d7a3bb4981c6c3aab7e5bd603ca7b8f475a0fb5e68617790b36ce752d5831f4ea35f51d3d1a50675d8eb52f1468871f4bacdcbd4cc676def54ab88181531c809e21bad0b53ecccdb7f1529a78dc3a7b4c3a032493b21f433c847022e0b18f7082ae6b34d11475cb1a0130f67eff08f3b1d0c67f2942498536eeb84793f45e2043c46900bf596baf29152219d93ba4c0b958a22724b5e71ebb644d04ae135a3b4b3ecbd96686dc674c0dad0396fce483c0b8708516347784e6b3a3c556fd2a3c8382b4cb92045eedd255cd9bbf3451a4683628808bde20c9a2c57fca94f1873741bc2ce295bfc6dde5d38e4fc0e142afe5d4fe2d97bb593f8913c8e9a656029ecfe6d05dde33d33dd8e7dbb38f5d0c2af5fc321a246a9333c85a3a97f35ef8b343a248d2254866e7be1da02bce7b83976a8a0ade525065fea38034c72adbd048222bd5534a4102d1ef306cbe6b5fc6160883b1f12f681fb0fe817dbf5ca684da96aac0c45f79e5a56fc8bf19991e8975e7c20b3ebef9b728fa41a55570e776c51cb553b3f19adb8967f662fb53cd7767b299082280e6b3f50a97b7a573d0a589715fa1c089aa23709022f2e608c63f5bc5e9dc4f85891d1d395b87249b70d03038de6f45a7d6b4ecacf952036558800961c341c68c5f2d92dfe14ee823e46d534d97fc7e0b0011c5786606eeabecbea0baa328881fc57fb11889b6ae58a1cd659714dc716cbda02f47b0489a1cb4253907700b37660a16b51bd3a4ecd5337b416310de534346396b6368a462f621dab552d2d358ecf19dc8d08dc12d817061f9637e7aaf5bf5f01036c55d3f90ddbf1a057eb5daccbc6d47c6ce5f56522815800431e20b1b0f30c2503658cb30aef6fb6f2002e2b7d6384b5c20d9269969bae59027dfb34024b87f22461d19c4bf8a105f124528161f28573fd36583a7f47fca4f2bcdaef66f5355f14bfcf9aa52f1def67432ba459609812baeedd128e0b5dd807c9c6ceac1a45545acdf7f88a445de742791c3afa3587a1342905a9a861b5ef161cee6e1581ba95238cfdc2b2a9758acd4314fe378919016c14a3ee113449a0f5d8189f4287c4063ac21ccf95d6aca69264af51a4e3a0491241bfce664da583df4f3e0f7447b14e1f3a8a098443b912a6c00cea2adb90bd472978dbfecf9fccd00836417972a7092ebcd91883ffa5dccbe0c5a66754256c59d47a6928fe29e5d9668b905ce29a604f1275d68a1fa37d21b64022055f65bf3c5e7c938a2f3c0a95a71efde3492e5b139075028be81f56b5604fca5476f2c439fe81e0e3ef174545c9ef9b71b750cfdb0012aa99752d41911718e837574e11e92fb89fbf5b674152e2814b995130312d04b970e924c7dd8c32c16106830544358140e491c5ffd912bc6b8899e4f93f785df36cd007637d937b3592d98a5d40dde17172417a0656fd551236106a27ae06356efe0d5b9ad469294f138e65115085d9e41320f17bebfab6bb308367e62de8dd334e5f1ebb2428088fa1aa6db17429e1b168149e76d4240c22704a3b4b9e4e4e98cb33803f148271f58bd16c867a9f7d2104bc410ddf491e135ceefab6b4f518e45a0cd51d3852f6779717acf2f94077a45745e2669c177f9b88d19f10f93f34f066506ea72a9e17ca97f636e2abe21e14d77eb6578b560800f3242a76896a076c781a933db891b9119be3c05d2d4527c650f3ac51325cc52fa268f9785c108b49e21827676872c037d211df3a9ae9fbb567ac4aaac2a87a832e0cbe9d12bd02d8aae99389075ba985b6b920e4894b6fa283b0b330d8179c5757ec89bcfda3447c9e763dd63f6bff51bf5dc44c61a14f2ae03f13f95c65040efa7008ec99cefea7024d38af440689e00f1425354e16f2dd9d21be8ad37da0324667be06d9c8ed0430bd8b2a73fa30d2381c66a7e0b5cce242f0e2768756c8c73204b540c2493f941599b2da0c395dbc7977f1f430f865b5545a13410d5e020b4977cc67142ac954dd7536315113d6d827d7e8674e73ad62b0231a10f5bf547d0248b8d1d6558574c604f64ae45133cc9d64763f89875d938a0cb94110512a945f1226f2035468246ea3c336ed504bd2e66daff4705435a436037bade59117fc4ce76e6332c6724803d437a85902d8a99f1dfdd9179f25e574bbe29d3dfe9331e7476cde3b6ba1e5fd1468293b4aa77d9f9f7f707b9e27d2174", - "priv": "4a9cc810d28cbd1a6aad332c2ca86a09de56dc729ad15f9f8cfd1a3a4048bd3857fe4c52fa9f98a2d29129dc4e86684057030295de1e3ebb3a3a25bb49dc5d00c0a554eb63f77db32c5166242269ef6457cc0a2e2b66ab69dafa30c5dd4ed98f1b3b087a8a154df7d84d6a62f749a3590e058ab4a72a324066937f7b0cba74f2e4466e2306890cc98859386c08b189104044134110a29661120530d2304410148ed02882241460d334718a146e8c126ce34431544091cc882d4b1826c436700a96301b3951d1444910006162a828a3c85144188e9a00519144501903900114825804318298802145295a9041c9a40892a6711a48241a420401a86418c80823462820a04d92a06122350d00160913426c8aa604d3984949a08d9120701209515a862d24438d58126100b18d00056620b68859242cdb164a40440011a34d810272481471db482c19c288180340000784a424251b472a820480028030628450d0b00c1a443213972860406ea11671c3444864b281c84000224600c396416102720a096550a0241841618206201cc34864042811198e4b324598164e1c856d848210d32401d0c229e1b84988b4251b914419c9251c240d0322425ca6302482690bc08c60a66000a789a1884481b4102233821412721100265912288a46828c24518234214b48520ac08163c8294a028522a1295b3861c32051c28269e1c2705a160e50440201892c424269ca3845022806088864190962c2100612a1698a205261283212a6045a800590462281122dd23680581029094311c81225e0c2618bc624dc9221c0246e1b4406cc308523028401139184060c998490cc1485a2908cdb068821456c40024110039221a82499c630dbc20c10b15022a36d8a387162264d1c922c52c225930645843481cb0682232328da946454846482960062104ae0466254464de0c22cc4c46c54028a00976c91384c24a70462102e102912000172d2807190a880cc966810162d0831640a445203b46c0ca340e1266e63146e0994511b220123916c0c360501b3815a40854194314b344151308510408e20186a2321898aa430c8426254a068d1300e884450d222205c3030a414681c45891b86899916724b9445dba4245ba440a4360804290694a860100421200610ca44101a4391231429d12270494850113590112285998488a2328e5b10815b948d1800450c2285539668924081c2488613183051440c54a868cc380160240219460d80280e52148dc2c08188a44823b23159024d11450a02005253c8441b4850a2b46941024652c608a4284982240143006299b890d2264602a28d12c46813374d40288183386e21326414a704e184111aa6615198901a0201e2884450244ee33649411069c1a88d0349225b986d93205120286821030d10b411d0924d10b3448a44710a0030183560823611c1022d01192a1c39094c3250d49424180882943692c8b6258b040d4c4062239705dca8205cb2255c204161c830e3a808e31804e2b60d20b14c03188dc98225933004dc282ee0320d233490082512da0491ca42495a18219980409440281c9300c4246d0b3766e42042102628d4100e12452e8c382988208a14912d00b5481a04862486681038091b3582a396615ba46dc98265e492510b15499a92488186641c2049dc3831592068e4a801c0a06d5b186ae2302dc0100224326958b250930202a3b845a31271a18430a3026ddcc65002b468cc3206cc10904bc86499488541c64c19349203182d8148254b3460c0144909257018b78d5918309c06250ca18d41387213054998a661dca23000b571110389200732213060dc28829c26255bc66d50168d8048528940458c922c18b66de4448092487023314dd9048554b04de0164e44400ad2b02c0a328050802d5b80411c9265a41482da36020095846238404a068c64b441041141dbc42950c44de2342009c31123172c020988134786001730c08480cab02504a36c43922003218c998621d84292d2864d034831a0164440c62d83340544b28c1903880b93201a23601bb984c0064c21190594184582128e082388901411200446d3c20c11a004c3300811174a12b57124b52842182a9c262153488ec9a89082806099c62d82167189a230143252c39430c0966011094ed0c8014084442040629028821b088c12080019315219280e4c120293924172f9004f798fcdd2b644cce4e454213340d306016c17476603be7c5b9d7ddc2148ec171c5aa11f03d8622aef3cb02e470af6306660c41804a1a40c6bf2ee70d888284ff6364b3a7598024f74a7259a3efb5f5ec6bbece59c184b5824a7f0e9ee352b7c4324d7a9c4ffafeb182852184d9bce2adab55942b9bb017e29fcf3a1b76d392a3799503cebe2128c94e13a5ffdd8df9930fed2bc0a75a60337cf5c8bcd3929d4ce8d2734ea12b6e631bba534b2bf2ba8cf72560dabe3596fbb9240090d2986e465c4fce913d0105b03657cdd36267bd5be25a4b24f87be1b94f9987c12c403d205e2dd89a4c3f89a8cf9ba2c9151c67c4b148b24e6fce5dd0ae5b390775b674573c54890a56b2a30a425ff89624f5c0b42ec1ae95547c006e08889a40a238ffb09649200f3d6c18c9942992280c0034ac534f7f7d5b7b90110122fddc750c55ba378d3047be45003d539f67fe52004a7b44332c8d6d9dcbb85019501ca21efdc7c49074ae1d624457576b23635b964154b18a2c6b5d4fe4bd1628fba5c7edb7d63c07dfc01f90a80f87409080f6125769f2d08317e1c7a071be60be4e3654923d787b0ed7e6194c150bd8e73bc2c9a90acc2e17505d3a0655a5bef929e257af17d7bf96d563924b3ee43fd200ee4f484b3519fc78493469e2750b50f48845ba6d7fbdc9478bc7c3d0af0d55b923b2a23280db202586d50713cef9c47c1b1f0a6a95cf6ebf9dbea29f8d3c2871e879f4310e0aababc3a9664668ca17c5c6b4ce08593ee495117fcec7ec79fe692b9df51c2b4fef82a288c8f212029814cdf2ba7f595efa64b3af4dd4f5d8cdab7e3ee11347e79af4568072b6c0395f407a22ffeaaf1b87ab53a53ede59710774b73a2aef1fea6beedf756140aeb92155065249a9dda1594d5da73c2a9f529f3fcbb8d92f5e5d6c71e0fcc7f772e662ee586a4a7e8a177e0627097dc2e532968b39526e28da5e5c5eae8d8a57270962d443463cfbf9d4abe29518d1ea1c9304d79320b2aa172d18a2c7f6deab89eba7363a0fa6cf8980b9e530039c3b98bb046526e86b407a68267ffba07551d9ecc49fa2369e4911f14ef87068f591434576fc709899ee15b4b20aa7836a3a2307c3b17108d9fba1563982e8aba4fdcb6debfd48620cbc3e0f7732e4a6ee2a39587e7474c522c2e556d2bb847a764da34ccffe991764a9b680c906cd1ae57e3c66ae536af188feea5b22c6ea5e13661898d3b0c000342483cafdf996e28ab65e3d9d4b7bee6de17249d87711432a407db376d957d1f6829ae1861a9c1db92d1ebcb56dd8d774ab902f3f741cefd07446fe9d29ee1e7bf01413cb80a12e5a83f0534a70d24b63e6d7b10cfcaf817e83cd86b6524c81f095fce2ecc9719177a6636c6733e7534900c1a6056e8c9ba52598433b5720c216f83367b53e97334e89cecd4ac4dcd96952305df1f0e0658e80e51f59065ba7cc0606528e5161d0e11a95d8bc1d8f328f135b20f568a90a6a5422cc4995edb0a1ab9a564e7a9624a12f6cc1cd0a2a00728be8bba5e293325c0699049b8ece122ee6e8811c4bea54d3ec0ed85b3c9b34a07d6a56f8d6273752e879eee62dbe077353c7993293eb91782db4ec7f7e10404a5e70b5f8fb7a537d755dbd1614dc945bb4e40467b1110d373f14aa7b128c395b3ee8d33aa3ba14f9fb3c737ad2e63a44b3a121419d2a854fe18c9108de61b681910136886216e2948e7e5b806ec663abd7946d8b10829af9042d63942416bf27c7497c5c949cfb15938f0e051a58f0ce1ee15fafb3d372ae62b54b7dd9c7aa87e7289352f0ab60875e6e4fa00d8d804a2d13708a0e270e8483dd355083c5559c649c7cdb569ee4a61e2c1c7e6453e3ba70647d4adfbb7e0241d5d0a81aa7b3feb64628a12cba275de81d1cdcea6c5b4601f3c75096eb89ec6d2dd3807a320640bb842ba147674369e598232a6576eeccc5edadb53eaa798cebc5c8d0a1c3c4e0eabfd4aa4ea29497a25ccb0b2c65fa71b0753db6b134adbb904792bbb3fc08e67f6a8644a7b9047b65f1445cedfe81a28fd98299636898c48c2054b847df5152473c0fde6121e87fb2b2dcdb794d0594764145a2a0d7df6308ee61acfd0b5202b0a451a3793e8add24437f1fcca70af52e8aa679e31434a30ee99c3fd466bd36155c6f59fdbe99518bd657405a7e422e2653a378122976d4d4d349fbd57d0b68437b13a6eac85426e2305e333240ee53490b23756d521bd859b873045cc8c01155d8110687a67972b9cbd435262f58622079f2b2f60808bad921501990f1c877c04c0297268378cef5e2df7865e93376ba63bcb26eb0b35a5a03dce97379268731ed8883dafe5035e43db4d81ae03908e8d7209bf83f62d48c7aef6ac6d0bfe81e8c0175c1c9d424b6318ee1c51e9cb2e22a724f2024066c96451bb41129c7194938295578773b55e4f295ecd627366340c2db8669f410a6a9bc974747e072de2e8a14679d145bc3152cdaf68044c63d1319aa2f445cc2faf16fedbda7bb471bbb61e01edb4dd6c0d33f20f47b6d5952f9ef5815f80d9f8274b189a257b01f2d7814357d3fdfa2693f737e6d7e11ffe513e3d3549b43c22d3734f582802c37efba35f547ccd39757d5c3aedd87def6706d2894bc0461b61a05ba0ee44a2d300ab2c53821b188bd4d86ca1c6ac2b5ad1f751c74d4d43b0ee36da1d13ed3b501a3d77e6c0915a8e91450b6b5e480a45b6ee7afb42cccf08c71bb8235e561430c0850ea141710bfa4591691dbadd1dc550d01081293a95cb311f548b7582916c41ddd7754aa9174ce435f0e1aa08ee78893c69f01f5a8ef8aa345111d8af7ec3171f401e1c72d6d03904922b929e270a56bd67e515f701a7f8f4f32f22052b92d4c175002eb214d742c64536e6202e8e01295309e84f5ddc89b88bb6fad3436d9c801af5dd456cae06c91ff0466dc197ec729dd469133418f2d4198facf436b39fa85af2ee59fb335b39a65b495544d8e667596158bfca96c57923b6f9efd826e1f6172f114f1dce6727b7bc664d74bcffc758b31c9d559fd0c6d26fefaf45e4d3e44b722e36cd331df1ba65d4e65e0d9b934444b955f8fadc789ef3f9c67c159b723eb25cdc0076f813dcac1fcddb1cfdc03d0eb040b472ea6de4d0b9227033fb30232486604fd5b863cf5d2b9c57422103e959155aeefa52f8af572521fe8206ebaf4747a17a3880fe07f6a7aa01a00b598d46508553459152e3801d9ffc67a21326b3239f71a8e3f24a7aa054677f88aa058ed2266776c7389204a1d48a39313b5728e113ede7da778db748b9a7bb944297e25209ec7ee6c4b41bfbf4dd3ec8a0ee7c723141021e4afb5923375054598e33123bd3107a251d16f347db64fb913ab8187b28365ee64b0721ce7f52ce7eaf7841961875131d935787e670f5538674272ffe177fcd78a6edda5a44b2285ee98020137641052dee5d9b644d77245dbf0ce99033ed0453b54ceb6efc47bea55193f4c642e245610915a762418b617dda40ae6d2115b1f7b70d2796cbca052d228e8a8e477474e6b94e3e3599d7f5408f6326039ff1fe49c151492bda9fe27ca5b74a5bb0a82dea14b5cf6f0612945b7e41171c20fd005899fc0436560b232951e1f546e1640399a588ca8ea7d3cba0c31dacf7a0421cba88ff8fcfb134d053539cf8abfc7c454319a3527b6de4d035931e33c84af23fa681705ef3092e0c54032378c5aad5e7a2ed7e43a883a5c384aad44d5f246b2656e8d8e0d88a17bb636a14f0d8d7f8ed8eeba55bb8d7f5cc217d01ab6dcd9b2fdcbfe93fb0f77bb7f0afe0a8de3858758049df5433bfbc8945579b695f513c4c224a6b8c8b27de1f232a1b34ee838c08cad72fa9cdac56ff0d660c68231bbfd0685501d003d2498c97830fd164d668b5df148829ee7f111fd3c43a68a9081495882898feaea8a0ed38ff7805b07e8edb0be3a0dc384ccf998fe20d8bc93631ec045d0aa16c245ae127be86b360370fff50c90b703ceb0f50fc1af8371c95cc09416d8da831782673e660c51815dcdf93e44e202f7187f1577c0dc462bc9f917ebb97133acecd7fce51c1be3ed6222cbe71878208563e99851faa57020d2f18e6f0a2515c3d43951897593bfe3d14c1b096af31bec0b2086c3388f8def2f5718290424538783cf42b09d48552086eab8a340f084dc95a596bf8ca994f391fcdeed4ce8b12a3164978c88aef934715cff621d9bea04cb295f48225ff68867113f14a73776f516609c8bc8fa9e5b5a9466b9a0e71ecc87faa5975eb7142a4d07bcf54e677652a29d7ff61a3a9188777725d2a0012c806188fe26d71844bdd58b546f22aeb4e7e14ad618fc80de3c02908b9f0060bac7b9ffe69eafd799a3ce60770cc95bced3e82056042a3131341b8ab5e951e97376001136924b22ec49e685e44870c5858b2de581b605a6b287765987719732ee1a5bf7fa7aa619a3f618c828d426ad2bff8c649a40a05ff92542cff1da5ab4588a10d09ee36bf63c4d6d2cffb64012eb985b5c76a9c852e6760a965ac85849dfe44f8754d2b1007dacf4efc891f47c168f9a80e3a4736dd60ea439714e1c835a4779694f6627131470f5096e59f4511c829ccb9d03058364048afd98f6d1cea9e17be0eb09174046e80bc49971f0f522b1dddef59de6760fa50b369e42ca25c97c064ad" - }, - { - "seed": "30aefdad38911921bacebd464851d5e57e9d9bd0edf2cdc68d4337f2277d1e03", - "pub": "e4a2a498a4f2c3704095e4bf3606e210a7702c22008fbf5ca113fc329a5ae99cdcf8d92d3954d4e51a266c252e8e4f899b6084c15ccde2fdd11a5c6ab342a9c568cecba2a1dbd399502c10f2b3d6cea36bac63635c8ffb9997673764363cbd43d32a85ea7f1b0af37604994b33a6bb4279fd4e57386a896f6e380147d089d36cdbfc1e12d97aa9b3dd4b2001458efc77b6f16b56d13777bc16f49d9fbabf8a353142805e2699741b31c43095d72b15191c5894c2e1688df31f11f2200b773041abac691eb979c86f3d1ae71f2e75aab7ca8bcae8fa7c7130cb1f3061e79a6be3d9724efc0793c438b572b915d59d8f018282fc3f0c6ec6bc62f2aa442eb1053297175cedadc743d43ed1d70d426ca608cfbcc207261f80f2246476ef1026e4e4bf078b7788bc23b13ee5a044c7f4a75c12638eb7c50c935000bf48b9b2d5d777873da874ac6bc9124f64e2e82974034bde8afa8659eb2f004d2d6bc7bef90882f563f70d87c27586a288b251511cfc063a3cde808dea8acb8bf4a94b96259f4296933f1d78c0f554bec9665dc46b072091eaf0c4723a3b1ae1aa389c796806dedcd4f17f3ec07afc7e2a3558916b85c075e3e6f5da9eda56e19d1dfa74553854553ac8506a177dcbbd4b8a8b55c09ee99294a3ec2e17010e129a1f6a589fc54fd4adc12293a709ee67c42bb4be57d6a0cb20835faa566a586939052dfe90ba6f0f6aba4b343b6ad214ad20422c5b7a6367b63c33960b89196e3bef8468ae40ada715fa139ace032c3522bda221736d539ffbfdaf0751eba06adb30189efa88d8edea54194ef1d6bd2fbf68deca45547a14d8c6fa1dce0b77a31868becf6b33dd272cb7a13c64aaec6205f18882cfb04bb181fe764a1eacb52ee9f9ca870ba484df1231720510f289f5f8f37ebb7cf7bd288a81dd26da47b95ff57bdeeecb91b5a7c0004c1673a95a1ef7cc860e9416e0e0458eccc62ea51f7226429e8d8991d5cff84f83af95561304a52e9399443e83884b3e2e9d621dd1342df23d29ee8d6feb72ff4ab613566df12048b46acab88086aa8ace1c5c75b626576a073bf9e804b5f263d32b746bc76ba822b9e1928d9d933b4a5204ee973dfb3b8630d46a0f426f7afb22e3de0e725fd9c42f6485f30ff49d8086949f097bc83603b6cd75466b690d0483961e1a653a67debd2838f7cede4d0f0cb7b3cfd2c7afaa2940f7dec344c3caddfe6dd39bb4ca34ae348f055f2f25711b8478e3aa1e09ba0b2498167bb9dac31dbeb451c56f4645ded27d4794e23a514316b99861e0a5853b14f5c105c9049b368e3dab253b0ee7d77b1737ef548ba17b653f08428b5564afc3104c7a73dde14b73d3207fb8352fdf2bbe0ac8974f2ebf8674d9275c27d6f92f7edec08a5e88f32c3039883c78f4806440dc2e4029440d92eef83d50ed224b74c2209c5040179580c49ff45e2da5b46b7c577ea403bf889f2dab26ce4c7f55a602821dddace8fb1e883c6f0067780e3fa527f810aba7de3e1f980471e1a4c866b3c663895da732bb32bf3a206bc388f6029318466150ef535e55712b77297e1718eaa349cdad32c2c3949fe9100406465e6f1fd980fbe3acc106d50e648deca328cc126d65762b27e5b1924c3cdfa4f51c1c7d7348e571d7216084cb792d1d5cc5dc4548f9bd63b630642a69c4cfaa18d7c9123f715fc66f762e90c95aaf7a7503cb632bb25358714d146ca355d05352d94dd73544bd0acc917466b502bf32351b7c3287e92e51d34f0e966acfd546c9c9638a388cc3f2fe29f9d7a627830701f7094e5e656e6432b95f95bd9e464ed53dbf794a472b340868a7a43d034ba2e826cb622420b8533a4d6bb0737cc0c2a2682a2b23962d47fa15e3794c5e201603a30f5136c00ebe154e603c0a2e3ba36644166b49dbb3b95d332ba8af82245e731ca2e736d86e637953d047c3c45a2230350101998dfd09053159d18a2be751d1a69d5367fd021334895fa943131f023b32449e4a5bbde77c0647a3f86e09bf4c1e61fb27039f6ec8ee68a5eb2198db3691bf99f221fa25186c42f45aa0192ba67ccca2e22aaec7cc7d82dc2606faac06ef83477fd2c6033ee6d08d3fbc0726fb16305685ba4442b0514e7d5c541c4641bac9ad17fea765ac408d9cd56b9c05530f0cf93c7bdd671e595eb9cc4b6c400fb21b430c0a76c57b439a7e39ec0edb67fb438b7cdf2492b2dc426887bc4bc1d8ed293b3e5882c7fe313b9a612e811cb18b5a55e88df13318f3d050a06a7b3b04116cd57069bbb7a8e5487c812f8d23df74e293fabc5e487482143c84d123e48e64c271e11bc361ba656beedcfba0122e048530b9e943558624e38037746ae6bcfc8033be7869fe7d61be5d6eda392a5bfb6c06a5a3e8c9757e06ef5c8aa9df0b3eb0100aad71ae83f4f3e529ccd4e1775bf1f408de1544e9ba34cd2d30672f5408a2d0c3172f36558840d050dba231ff30a32768ea53ad28a1c511ec4d137b1e2743b61848ba894407e86cf6402910e1d19970a7d82decfc6d76be3ab35fd1c52d5664bcc09ade4c4b5131536b895efb4b11b202bdff009fb71dfaaff4026e585575cf6a9e69d2814477971e2bc991c24a73cbaa1bb1b23602bb2d59fc228ddb32ffbc8dedb96ce2c169a596178ce15ffa636afa2613a2ff2264dade0e5e2bf8bd036a3a23b0b3e82066712ef05c986f823c0f568cd3113b86cdb43d4df50f9d880b5efd6b37ce0d94eaabb34705f1ebeca05c50cd69e63f461e52191fd5c49280756498c633e99b6d2548bc3fc67573c72d0a20fd3cf0294c320b6204f2c88175b83c3be93661f3957336845ad88a92ef2ca01cd234e5e09af202fd7112a62b8a1729286658a9a9deefaa47a40a4f7aa31f7ce55c1a4c44c24e5c8c3ab20305a8f4283274025db88d69eab48117bf760e357dbf3b7497daf20f2e5d5e2aeb9aadf36cdaeb6a62d033f7c5dbb9421d720e9e664501e365c86dba03918317a0c927ff7dca924cf07f0cd6852b9e35a604ac65e1c63394ba0d85a709d2ff7a5e51e790fd2ae3f8220d139d3adc4ce4217b2fecc8372d203f73b931292c3de82cc0342ffb50910e48b33c32c326a4e7751a8677e8e85ab71026abbf0783cbea6609f462f210b7ea1dc148018bdd193a09443849e9a97f084a03b580dfea82e49d51719bd7039e49b1ebd6e158bc399faa25fd39a3baa3cc13f7310d45ecc076e77343bbb5af1f8cdcd1cbd395aea6d8505f18303789b8b7a7873dc1b7852763c7a11fff2c12e62669fc5038ef44d64d5e161fa0bc4af534f2b1c4309db99b89134c34264b1b1ed2a12213f26efb7bf68b70074acd01f31cb16f2036021f200fad62946173a3abafbfa349bc92eda4c04a7b2c877c6cbc7b3c72b909076a2589464f56a7d913c1870f9efbd32afad6e743bb6ebe6bfc6373b80aa4452a096b507e493f017dd32dd1860700511ca8d49a573d2dfccf51cf473fcab51c8986222fc09aa2d67735bf0ee459391aaabe1504cad933358724102128c67dbb63089bb9a17112d79ef92c2af149a4700ff090f76096a72f9ef4c2815149700a3aaff9f10bde057c33a77525a329167a5e9a79f4ee31f3f44afdfae9991c5302bccf957a93b22c99d6a61abde35468fac59ac2a3b91a26fc17", - "priv": "e4a2a498a4f2c3704095e4bf3606e210a7702c22008fbf5ca113fc329a5ae99c63a56ae6f2e09b0871c725c7bfe69390179ad98d285b79623e754413aa9223bbedeac1e149ba6f3c0af72f112c1c0fd9bff1114f6bc177498abcd9b3fe2b9a378c6ad62ac0e085d355e0ee1c58839fc0fa22c946649b8a8aa6a9d20c929bf47b24926d09b771983624220546224404a1a28812371101a62c4aa425db806d811644589269600491194404db326883c66861286402900440b64192080e10208e2399800a218608394402c96114424214161160a68c19124114380ce29810d9480124378618c701231728d332264c14654b184488928409218ae3484aa3822102c2514a9280a2342e63b07110098ee3282d501670dac410c3488902b43103096a10192c0c1621a4c26c03314e1b040518125194147010292e6342820b931024300883148d84280518a65142a62d20196a08030c59340684304c64941109a630c98890442651248300d412300237610234419b284204214e62a0456410528ca44d1a351162182219184503b64820852cd10821c2081021232c80b89018c471633870c0c40912004488b86582168d91b2701a0808e324704a922d492052e4864d8b4481c2104620256c1cb624c1c46548a844940269e324288b202080942cccb2808aa6801c249124b180d1b08de494892420314314325b3232210889a0a280da4492d986844a3401203521db2620a10606a0186e0a2905d8b461618811431401e00600d124501a8405a0a04c13182193a071cc2631084850410442a40864c9460a00c88862466601918c04172623056e001001d13245009231d10845c8280a03b6918c30251028720b2245d91206120361e1248513494280242824482aa42466242811034142e244015ab810143925a2a8049b088da046428aa220190109d000040149494bb64913b2444248700b020902458d50a82189146c1c2132c3b8801b13908c38851cb8281c980908949050866c09178a6032290b416d20436c1b0748a0062420808c1a23641ba4310241815b9668e336415a248ad9442e51340123c749e2a42084a22940366dcbb024021731cb86104298088b303113c10558429050366a1ca04d00057008324541404094386e1ca829d2b840183971d3202959c4244246904140820c260552342609099220310841a0400b4124c0a0405036682305291c1249c3b031dbc450d40245994072db3411192531a2c6441806005a925110896140846523812d14151264020202a511c94064229229822480c49811934686cb92300ca2005828111c394023b288e1860c13826ddb1828829449a1b461531250d884442226092306411c928dca448c8a3411c2c011c1303188380018194a989224db367252b628a4109092c20c14145280a01159b228a0b82483288a40a45083940081066e5332721c8205d3864443c888d0368c1317851288101a119019b6244c164ad1821189304d5a1246942832c1b629040589ccc24160c08120c449d2c6442426314236464408859c1010889451143088c4a84d8ab24821006288a205099665140000cb22911338700c99281a30221a3589db268802972801012d1b347109c3714c302448820c08160c009684e40284e4384221866d02148a80c41112288554b08081a400da02718034918c106409390042862980a8040b436a44a43159b6096132224bb810dbb40864344293084de13026d0008ad2a469c8960d238429dc144a0180489cc4311b026019a980db400d13184190c4500424714a18850a80002339884b1688002970da887083340c0a12220c880998164c1112925b1684d1168e0c268102b3919004908ac28109974c0841689b820d0949284a984111408623364019174802c90dd0348d20a830a18009432090880888cc166a20c74c8ca40411870d0b0411a18288511484531252d886249c0069190281942404da304e08b23100216ea1b88ccb966508980993989103a32512b80000a6050401529a3269c21410508408d840641097510221905a0432000424c12624202171d4b45052024e5340890ab32892304559986d1b3446048128da94854cc20dc0408654a68d899460d0486ca2348a02c00902002511b4891c181023006194c6011846860b486202068a20338a10370620196d8324860ba22dda9604c0482d222760c91408c2c228cd7311e3ff75aa5c1c3eb526be1f6899d230eb901679dcc6609cbf1219ad77ff255876f4e3eb633b6cbb8c970ee7b1ad75af731ef3b6d0cada4ae2a0745b78c9fe1260062a4cb330fb35695bf7aa350cb300793240e4aa44ca8a7bd91e39a7828b73423e8611c36e135991a4be5eccd17583afd448d765a4a4895e228ce1840e3dc7c604f696c76e5ba6cf0396d0d1ab7aa91e433a8868fb633fcd919f91e3904605145ecc9d54f86c415a3fab4967fd61102e0e1e6d574a8afbf441a82ce4a01370a6a09652737bab22832b6f764424e50b9144d7ad62d15d4c947a3af33022f4dfdefe02d14c2b8a1afe044dc0904722f1b901aa7a5f825f435ab629128073771d69ab4e04c75b55230f7a33e14d639cb1a07277cda8c57765ed4bdf447120c629bcf18ecf4272762dba34d450ec9000cf890cc67b02c6aa26ce098cb31655d36a04e8cd5406db2d389c702b0dfbc3c806249905b948471548b1e939a18deeb27770dfc4ecc09610398f3058e81d38cfba804aa9d2448250512997daf158454a927dabf38cc72318b60578af52b11a74bddbdd198225ed13aa8dc0b58a843cf20e7c85f8fabdb5b06dd702e849c079e01075ec5e604c007cfeae6521bbc0e9b32661f8df95eca0cb4a35025d5d3690dd88494ba5425dea567e13a9d464e2010d618b2bf46a3f43133024ef201c81e6d36195791d24174a5084272a9d172cd0667cd80eb17b5f9fb71bed13145505f34d40c27fce0876ba71e77fb8077b3b6b15a65aee5b041bce1568fa87a984afaca297efeced0f06335d565333c666536d5e43ec01b2db59e1640f4232cd23a4d619480fb5dcb104d9179d1ebe2359b28539c4f48e3c9ad5d2d32b18ef700ba4c62dcba840482db5e6f379fa593cfcc00cc0d765e0efb66b0eceabca5411ed51510550c95e9321bd6a7710afe0c99a3a4da4405a7f85d23b873ec9bb8aa1a8471f4404b7f6e2c9f8e8705a72cb9a650793ba47d2c85562cbb44e7cdc73dd34be370fd22d8887637b663a3a7196e2b3347172fb86410038ba986019da5c5489150e220b2cac2a9ad0131e6fcf96ced5dcbc5e3389c8666bcf38768af08a84e2c9773c4d31b805969e8144fc1f4c033ac2f78768755443e9a49b128141bb79e585907d8d4bb474a85aa1ca11fd608edc908b103565232f2da96d7a341d8c8fffec1b1e3c620df52137b9ec0f67493e4321b49143b3e2f9f0ef2db83d2a4bc8c6ab53181fe25006da495b0daf8c1b998da34c4f5ffbf1f1e025f6a512b5a7395eabc6fc2656b6fc350d00eabe9b26d81b89ab5c94388623db84da05b0090fdc8b360d2f2233a27d0a853958a02454c880c04124ed1833ae348ad0c7a0384acfff46a3e7139b10988726c31c81bb1725f48574a57f73e76aa548e850e3121eb67f5f8cc40d92b5d27e6fecb512116e9267bd4987fc8590eb18b96b284fe883211aef7d376da25548fdc4e167a3d9985d03086bf303cb8a4dec2ee2f28854ffd771c83842deff2d4f7957d429ad79a0bad3b77e86cdee47a68e3528eafd31e18031265ab324400b66cddb0a1812aa029023790f0141b5084c7216955f379fb6d7333e2eb4cf9bfd711db218101006e94362d911ce74b5c98f8f925d5fefab1502c20c3d523bd3a66d169161649bbdf924c25a4353be6d168ae24c267b35a908cc1ba30fca4796e2fc07a672dd91b2a8b1acdbff727d2ed58b3160afd8cf5cd7db0e1b2587725897f05c623b4a5fea11e7de4016082e3a6825541cf3aab22abae509e7e58aa809c1a08e9daf59a0ac6706a658728691693f3bd8e8917ce71ad8675a878ee2d6515c659ada0a20cea963d322b608e6d8d62c1793d63c8712aa673f9fe2eca3f55e77c49984b7722a5f05c90065fab3662bcdd114123068e3c86e10ab2fb588141c7c083df2eac73fccedc44c23641b293bc730f113d3b1a5a552ca63433c6070cbbf6d22c9827b738187d0305ac9868de662fcfee49a8be37965fec20397c77c7ce944019ceff2fe3e11d843ccf9583e5f28bb4c6c8d737e37346db17af65ead105f4b8d8165e376eb5968fe8b8caa337c2f7a8661d23354fbf86cf773d905558bd6a9470e0d39ab9b3fc4a35655e440d1383d41120e25055e0fe8fe4b206b5383c989abfb245877b6d89ae565088ae25dde5b6e7959fd52b7e3de3734b3606b338eb73e283c2d422b60339a7482c8cdbe05bd54e487fc1e0d532f049435a53c87f673770d249bfa4ca785d04bf03bfb55790d5db60da62f17a20c8fe144bcc9d653b67ca6b38ad46f11aebaa3274b53b68141b06308bcfa42f1f586afe5d4927a0afbf1715c2700dc6389672dff6d6a498e6c89d0ace1f44d2f286e34a7a799a0b937a3f47fa117ff1b40c21a40d879dc134132a8bd993b1c89c678de4ad3b9eb378d3ae2537af2cebc7d0206a665732fa594e3ebdb5017be91a42c3dc1ca697bc366c53127541fca5c5628a9392b5525f2249e23533b939eac501edac55b196ba3c770352fef739ef71053921df9bf4d1c8ed539f83b09c2dee747b191db58d2e98845263bc997b9b6df8a49c4576253f6607f19f61ad9ca0492fe2335d5579a4281bef8d076ecee7e9469e0a2762413d2381e87e9673914a82f0ecdaffa1d0fe615a61bbbaa6b8357de68378b1c32804c06ccc5d554f2d8806dd000f0efe801a382ed538c0dfc55a442da1727300436e00f1f4f9a99f9682b62318a04a1c4a8cde64c0f27ebca57e5f2039d41a65814c88b6d587205755f25573cb18201379e6ae512c90e682ead15383e454471f9802c84cc46a092ff4d3d5155b003c20b826a5bc53f58092edbb97cc895e6a15f83b4d61b77086250cb8f7f59085d33831744469b069137cbc68e9f5d583d4c1e28311e533cd2f230d06c60ab39b3edc92c84a4e58852fa261c0f757dab5e75e3d7f883cda54e4dfdd8d157844b6fd9c797603b5da996fc756830b9e742ec8be4d5c4cc1c88167b0fb959f6e09e0857344ecf21df87b42692d8e7acb4ca7c6023f3f20a5ab6d08a1407c1fd6798c93c95cd43f875466bf31f2abd2d46d09404ceb081812486a732012ad11c147a462e83db9f86fadf22e1c278a9689fda682dea03975b0a7d1f9a23b050d6cb6346b90cb88674391e874a80d0443311e74cd61c5e2662e8982a5d130f188a9f32832849548cf32c0483190c596170d8cb50ea35fec68d919540a3388cfa65176222e30039d5f7effdf8baaee395fe9176782e6f4a320bb76fef38ee8f4a1c91a81fddd19caa238307c01d1a7615ad401de6966024e8bb64af34669304c6bb5f0bf5094e85c19b2389eeffb320ee0b9c66ab8bee46e610c041784bc3c546f3b29d7c694afd5f3dcb986c6771582facc09317d9e0c81a57f7455068ae12f4d50a4b533cd6fc3ea464a858440725f403967a6144ede166d9dd96c02748462416a759f3ba55f7b55a085bc0d00aa0dffc101e242d51bf9a35e41a381fddf4553dc2b778cd2347537dbe5a6ebabd22d6ffbdaa857d27cec23fc0534c63e896b3a699c5acf62528255c5e20e5ddd728e667aec965ed67d19563e687536fad25904375f24f963760e38a8e58477f2688ee6ce3dc57df2d76ec8e3a73f018fd36c7568aaeecca285b925d465b6af8ba763ede24cfbbfdfaeb18f394947a6b0d749d9e67575e2817b0b48d3ed2270f21435178b2f0f6bf921e740963808ded6ff9e637bf326685df07d94bba4ccdbbd05f27fe1d49cf0b8c1a62ead08dc672bf11078a5cf3733d2a5f645a98d89b62ad90267c5f11394475b1b0f195eec21eda1779233f7a34faff406e8e26dfa0d71cf4ef7e9f9a56f0cf99614e79b6f3f9436b6e9a97a0b061821fb7badb4fda7ed04172a07701fccc657bfd57917dd62d44c14a7404931afcbba0df4c2e0e9f52884f3361a291bd0e0d1b8a3b37f909b131231dbcbdf721a746564b135331f118b43d264d2fe806431606da3e0348bec5c2bd844ab85a00bcd15e04c4b9eaad857367a2f385bd046e2ba767574cd66fe2ae2bb580e3a9b220993d33bced873497b14ee4b87464e64af342b1e2aee63255ee17d6c09a3cf28beb2a42ab3cf6f84771aa04be1ee589185d54d03263f128fee0b5b6de2724f4d890af40bcd66c03e1f7c2899c8661660116a550d18e9f2bbbd18e7ab0d3e00da148162559236b410a6229b01d0029af742aa73706ccdcccacbde12dda097d1b3db12edb337af6b8a842da233e0c868b71a3000b8b06885bac60f690937353697a3a22dff608c3e032b597eb7d821016a865f3f62859ba4eaeea04e44772b3b79c90a7cd53dc45d5732490d6240d634b239363082f134fbd0d31e00c46d6d0d679352eaf83620f768d7826f8baa52ee2a1cde103102653f37a569a7e5f6c77b7b30b902c886b5b00b9b490bf4c7f3b734bf309b708877671bb45f0bfa34362af4937bd2f0a18f9622c66be941065818626e4d14d4eb5d6828de1a25faf9f7ade076810ec2b4f7edc40ea78d062cf073de89237433bb030c094b2d39737d43aea97e2b661258fb272de7f449e224f931fc7dfce98967ae92f46439742ab6bf0158c348518c8f05ef568a28e7e110e5b63a0b919731dda6a98ec66cfee5098134fc1c8214ba17ee19e90183c8f0193f1a3ae41254355c416c9ce150b804321175e2e7b4522c60f82bae3d55fa4f330309b" - }, - { - "seed": "b50db2597b4363f22c34276c4f839b7381518b60c9096a665d063f67cbcfcde7", - "pub": "34ea6b46ee5e7b8c15ece41ebac85ae4e65513ba546c5818e3b4a26b96efbd1b44eff1797ec0f8160d8beaba5ccf3dc5392ed5954c0e17e03c7e50ba9a4cf111517c9a1521a92d8b809ff6a8865a9d8ea74b2c54fc6f63f5aa2df7ae7a39c6476751bb89fb55c085207d34a02a503e70d318b48dd4b6371a0fc65a9324e3852a20dbe31aafacb1c42574a57b7a447412ae774701a2b2534156c19ee200505b5f6b11954554b797e3ac8d78c9ff3e744a095f5c8869b4c08748cc76a3266ddce00536e6efbc640525aca9962b1920f923091a099c1ef1b7abdb2d2df873adbed24628fb0b1dc7aa86a6ba6c1b784ff68d9c79798657dd17a1b2fefe4416082f3941b1b8ea6914197036bbdfe73efec0dce65f997d07dd8929c3ccf918c2b115ee082e6f8eda9463bf529396ce6b34a2db0a71f45a0077786f35af2075f379dd218b9a76acd3f1c547dc3dfa5d588b6359ec13d3499c8dbd5f1f0fc7ccb3b4bb9d93f441d3dd9836337dc4d07cdce6976a004947d382d97c02f956edaab0f0c611c3a5958138ba8b2bd633993496422a5497310e415944760f49d8e009d3379b8af0d9d17784f4ae0789af44020e8006789ef97377380c5acd02a6990c450b4ab39f4cdb9120eb838acfd19ec0c99d49a72c3762d83d523a5cac14594cf310d07b14af95d392c45060c7438871e295438d144f746a94073df70b6a10f9aab4851582bb1d80797aaf119188d1771dab01602d48ee3ee53c466a2232f306b34775574b4d8302db379e8586489e56f44e7cdab66dc38ae6f664ab5d9c23f0890df5ef0b031457da82ce0a5c331abab9a25f24dc75b99075dd3ebd5fd6c3704b9795868384b15e5f2f9405c8a8ead59547071f12b6ab934ca408476731f6fb17884af0a01492bc97167a45f4f538ef32c6be96a15a1dc4bed5f711d47af6061f4a5b7fc6b0fa5ad5980ec7d8dcd9813e1aeb29fd02dac49a773ee4e64a2c48b9a7930bef13b1075bb31fd7de65b51973dde331f3aea6c6760f28d7c0da39bb2cdb02134610da661b9a0a309cf64bb0dec55441f765d4b322e7550cf0ee1570be2f95666309c718ce6e909cc5a030c5a40369d56831c136be5c5612a72efc88874be8cf704e17e89179bd22b09653d74c688a4ebae6a845c6df86bd9b1fbd60772257e3228ab3cfa7aa11fdd8b64f8311d7f1237516c8af36c975dcbb05078b5e4ab618d4456c348dabccb79643a726d6c8e0af6df6505ee8f0fed13d5963f980f54f49ae76ad036c2f7aef429e5118508916d4cd7ddba541b687b4301ba18aa659dd0de7141a305006d5ca5ebe302c2439a8e1fc988a60b4604e0bdabd52631db524c76f84a3dfc641a276b4a8313ba8d53b1c2dda451475994d45cb96bd6ccec49183ac2b0e41ca9dab8875ba7de7a285f02b016e66302574db7bce4a02f239b1a53ac0e76f4173b31ba08eefbe15713c3eaacc5f48d51d08cda18eb830653499669c70cf3a4af6de1d82735bb3ff868dad75891bc6fba56959ce605cb3f3a1ca14ecff693fb0e01bb6b069561b3d732e2fd08c460f03efede6e03fcd538cc431155792a3b1f85c7964dc7c0a88cb667f0de97cc0fc8ead288d3414b741a481f8ee91ef33f9d4d205300ba9f7bfb71cd958c0727b5f8fa796457903fd885ac0b07b6dfaca8eac49e326b2ef9dd0551200d06f7363414fe988af18a35d35278be94771fdfea65e0e8cf65b9264a94bf092bb7f833550b00def2c083cb906f9655a9a884aaefb25abacc37cbd2f8ecfc3853f509d7e4282aac825a1dc8cd811f1b8fa67bb3d239774a8ffc4c74f856315d1f5b5de4480c137b68a75c3ba1e74d9b498da4d810677a62f965ba5cfc033675b676a506dff6d4a172a7895d1ac7e66d7c6ee6dfee2cc52f7c6d84af9d18f32a888f320fcf3d5ea4d852dbf4ed4f0ba253674755d7635e4b5897d9605fdda533d00bc9285cc68533d7f7e7b46cf797d31f46ff44a448fdeff06ccdc7f1af841fb071c7f5f37ab10535b16f72fb7e8546deedd502abb9e994fe6f2660baac80d5b1374bad13c4a0f713989222a54902dd4785e70c5599979bde61cc14b117054f5bceca606c968b5b7026c036d351a1768d03b559f20d4504bddda465e8068ed46c5a874ce96a3dc40b0d3d47f710d0e5b334b08d838e6abdef07f6142fe11ea40e4c9981298c0f9752ce63484ca53797186220907f881dec42672081b2c6dccb9ba0a9c9499ffa1841866ddd31805dccde608d777fcf67259e610b22ad6b8a6eda46aa402fbd1e6d8843dd2e7c35c5c8246cd9aeda370d65a07ab13f442803fe5798157d8726744f1e18ace452623aa90148e59237a04a92c670f71137b7ce803385298200166df474d4859aab623eaa82aa44920da86cc58b0f433b439ad044c0b4730cd58a9f1a90f12e5aa9b3d00df2c32614ecda513389ac2a27f709960f52d65c784aec87a60f572576d776221d492b4c64f4c4067e7af832cce67b65474e7da6858fd293729c82d457a508ef395c7adc82962491b400d3bc99ffed7ff1d46f7e2ce37dbf33847b9da8a19a201ca83916378bdf56b239281801282073e4d6739fea98259b52172ea3bb6e33a971a2cb3f3cbd997475036345db42aa631625d07f843a860a7bf32759a9f89ee1dd33ac7b451812339e6f795d2ecdf944d95a975123b44c2b9349ac26480350dedfe292641a521b6df5aabd78d0f98e9d3f112ad40d0087695db48a02b4d2a1d7d407006a49426733323af07e2e2485fd2eb8c93c5494ff3ca6ea8b4d2939c749be848f078de0ca1292d11fb04066b3316f68567d9e49850fef65a19eca528686af2471e8576e7a497fd9fbac0cb098b557bd3a19007ab11a84b0af3215dff15b3f486f1a8ad2ba5c9b55694c0de63e92bd2a022a1384b1776f1deb8adc5b921e2b5b2f4e8b597c5005491e8254435466d6bb230575c6046825eebae7e19feedc77c107f37576b8bcb68a6d1966ab6dd1c9e295e3cd1405259181cf74674e3793267238d431569206b935dd938c8e785b93233d8b01e599a6372ba5668eadf1ea67f841cd3cad5690e5331b95cd5f641511957c7f8a5866728373eaf49eedd79d8a668ec6433bd04d22e3097d7a7f3c703d6ec47110aec77534f6f693eb675fb7bbf5fd82b307eb8846ed7199d45ecf87f85a6c51b2ee4584f3f9526e6dee374d228eb3eb0f84ffc0a270fdc53da499a2a82a2349bc4a70d3e1f3f7f5036eebeecd551db2d53f16144bb8fbfc1a69d0fba2b61657ae1fc7f538f463be0481c7891aa9eb75f5631fb335fb5aa3e89f4b82e18f4450b37e399793f45641ff6ece35e423282ba1e1452f2eeb904b658acfa70bd84d3317bc4c274764a8f65abf8d488ce64fb38a7a94153784b7683ee9043e2c845a634a34707d1b20ba10e4577acbe1b46e04d24a5fb4aecc4a20744f453f4ec9b066c519c3f964f3220789569befd85903833c82e172033a0b2d4e28c86151eac13547ca83b0522c6acd02f1385d6ed31616d51c947494e0f101b0377d14970258026b6143a10a67fc6fd0275e3b4cfa696bf43f85f7b402aacd56948642b81044ddb84c8d496f029fbe246e366aec42d65b218b175210afdfa48ff8ed6c5807b6363e36302ce251162c722fb8f1d13c1a3", - "priv": "34ea6b46ee5e7b8c15ece41ebac85ae4e65513ba546c5818e3b4a26b96efbd1b6dcdc612ae4a9517ccdc498041115560e567c5fbc2ddf843e053665d2980b85de242ca5d23ebfe88f75171bab3dff0d11672960916633fef586eb0868ec65b47c41966dc8952599f91c3535bee1c663f505c307a0a76fa0ac08d5884571e1e925b12298a3862d8a05000854c1c40100381508088898404460299680841060c0445504048dcb60c10b68892800460348c500225529825222300ca3829422270098130c818211903819c9248d3162c1cc564c8008582b22d839841503049d9326808b380410842490671e3348882180920384e8c2230424600cb380ac8247221a3118c3061a0c2618122088328295092418c024a2123490944255c168e09459103178ac880885034461182040024040b32500bb690e4a4404b362402b2415a36005a18718082519a306d00c48d0b452a99a68c092926c0209243206c50a89054c0891a090291464d124309c800202239860a183290022053826d10894c23894518b73149102e6038861c368422830453480d84802489264de1325209130e08026d01002852100a0c370ce38430db847113a40119304eca803103324d52242561306e0a032208423048940dd0940900b85054a429db3262cc427123458e5a186a24a709812801e2a220a19405cac88c1110011a4146daa6059814711895890084709a442d0a46008a883109b96d21412e42086181048c11851009a84148026a622632c932094bb48523132ea108515c3405c8a2200a336a58026c990281a0464e0a066812103203378e00b58ddb449014062608378d83b86cc8166062460618006d04060a84b42504c5251b374d14a6255bb6894c182e22414e83189190288a4190510b21721428665ac4209b00268a82448cb80d8a185200445124c704121744c8c040994404cb420024c951c38468c4986181b630e4446d04c26d4b844158486a0a330e84a4610a4402618420c89470108830d918664a081012a600d194285034708840024308524832850b0268241042038150c842844a868d44229188b44c90224c02026e242686c19041dc202dcc023109b92cc2922dd884054a802c24406800829153b24c0b116d23a824db04490a250111a74041369204b81122b04100319254468808199143100163320298082cc9326840242608314e149964530870c8c66c8032281ac710e2024458046aa02081d9382d0b4640a3922d10098c0948401c386560a4241cb205d34232a2c64d12240984a8040c4521d2148c83824164246809422951a644d292300aa50908a5284104211ca2711322712491481b220a214868c0a269ca4661c494251b344523374a83c6891c80908c225293c06c10240608a410814066180788188684a3b4800b224ddba00898208e1a404a0399405cc2881a204da23208da840560320a0a05891c46605a40291c02515bc44d8a18244b140d10856c9186295000110b370c00868899944493144511b465d8322452b8295a042a02b509e0881021b64d1b97808224701b82200111454b004594922920020823042449a465c3b43161042ee124488c2022c9b00c118520143388cbb485a2386053b4654a962c234828e082410c2330a48489e3c2812122500c94880930300080411a8721db246e4114849ca8495ac86de0324c0137845a3482e1944123b009a14481a04632d8485080364a5c04084410485ac480a33210ca0625c1106a14c83123c20440a21062420a883808c2a2010915240a4611e03841c2423111854013338404162423c18123b6001c136ea2346d504291632086cb98058206120447121c898d90046048980454b0640313698b9431011742218645e43470d1c0459a126409250660a62911b2715c3848e218410a09021b064c5a020e12a8511932004a1090012920cb8649c8b400e44041d2800dd10691c24260c83089888629202866cb4250091028a19645429830130852ca9850122864a132058a122e18146d9c862802c908d22069081081c328705a80515830291a956c04c08d8294284bc82109458510102188c8410148421b260d84228a0435042102899b480018980024a350404002d410009ab68d0081410c010c02136080164110360a0ca825180085e2b46c022181ca18050931861ca4480bb54550c29022112159287012960493244874b8e275b1c662f98006e13420c8eb8d096532f633ec0255408bf865e3d99a238410ede64dfca978a9fbcaf096714cab73b2d08eae945b56ff3815ee8ed54725b7e7ca93723c48c1bfd4900f3d8c86a337390a92c66e58937c7e0407bc35418e3e393127cec56c593c92fafe9f14a382ae52f03d97592d56e930db5d9773ddb967c5e41a89a781758752edeb1552a52ae9adf467e1bd3d9ca9823a7ca0fbdbb2d3383fc39337970a07da7443b5e5115139505497f1bfd87d955c89a68a37d23bdfff675338428fc7cea4e7f833d307403b02d016ff5a0894602bc30c0726e41916033064c57b556b6c4bd19142b199dc817ba42ae84116640248e4014959aca110bdf579fd97708d25ac7f2763a3e0f35537c9c5d574950b0d7ce2f3e282ecd454f82ec11a2db2d59b5c7cfcec3874d3f8bed7fd6941bf9a1837236fdbfd1b3fdd2a5620e088016c7c7c4bff9b04e728c7ed3fbd6b14aa1a9a4903aada9bf73a83527924693ba51a30cda98491ef273b2104e6bb360e54daa8ef6e6925409f223e7d47dbf2283656cf840dd0429d27fe855880a36e90d84221e0422ea0504df29f993f1355270dc578a116e070eeb228c09a102e0499c4ddd0dc3712919311a04d4330c655c505c740cfa51b59c22207f21d0a6201aa859aa664f7adf35b8fb06985336fe7c822ca27190bd488694f5859389b7cf4964e96353341c92d750d9cd377867a29e6fd81c27d5b33b2709a5761c53c5934c69527cb6a17360715bfec973599c98e33fb20fc88131d50d278cabe0e0a27cefad310f3245ab80171fea6656392761b84f826c18c7bf4a6f135fda736e071931f01b59d131786406e8e52da602323660b8a5260f402b347de2b18d3f1ee90068571687ac5e79332ca1979beb48def5e44df8e2fc40ffff808c928ad36f74964c6bb7934b6e3280b11e8d7d7d0aa6b4aa5e6a11d8b1642946eccfb50d4156309e0e0194bc21b91b5c63070a1a0a4cc10e66a78f823fa78f4acbfb22978b0e1bbe73475834c3bb9ba300630bd3c426fa88364600630155c3b88f9075b782974f8fd5bed9be420981a293a0a600b54d421a4efb9f3bb30f47f97f4d4e15c3bdd809e2da235342e0a59a25790173f4d7640ee674fcf0cd0fd2b5b8839b927fcc7364b4891659f4094041be8ec2778b0e89109dac23cdabb3729cf248f2dcfc1706ff4a5c0784eb18f2e58920d1b7a574efe333d72092ff1bce0c3eca7e48bde40e822e603a126ab8239421d055e816068ce88d8a43c57f75cbb12192baa63a7a3dfebad146a47823b530a21b6aa6be92a54eecf1d6318fafd5f0b06a1311f1ba7a1a2564ad6ee0bb3d3bb10c39577166f5eca12305283124cfb0c048b4307d54d8ce998994b0ac3e71db4d110cb48e4d246b08e27797d0881f4c8e3f0903c75a99f213ccaf3c9494e906228a5ceb55d9fef82b6b810ae0028b1760b4ce3094d4ec4c3f8773ae0414471d5a3162a1887f7c1fd79f045c24e66d621e05ff3d35925ef7c3e1266034e3bb6bc5f6b509bd4f1940d636db3194c8f4873458a90ad3f13040e20a625b0015e3c27f6b77677c392307af8fd0e8600be04c1aff302aaa48297880662751e5d9227e3b49f9c5955f8bbfd2bbe4db5a5074699350b75adedbd8634173628ccc0314f232c8639c4ebb6532c223fc5922fb513c6e78aefe3497f4037e275f94299c27dc9363fccb09d846f0a8c0a73e5d2e5603f8030c8d4c54dd23904256a2b79288732dcb9d0532d9bfd4cefc789d959a9b68d6729efd953ca92a6f7c54fcf5faebe085131181574144db1c27dd9617b031abc06b9a01e32ad1a512eb1c6fedf772c833b8b1968763d700e1ea163d98433586b8d271fd378c71a3e1300a5ce416ade2aa0d10774a52b20e03f3fd81c7e4d5b68f59a6b20420c1919f6aa81d28a6cc2cb00dc15f10d49834f0dc3717a0b964ab8f142b4181d13481e167a7a1273135d66c4d23257c9c36b6ce00a21a8d97c744d390af7401e41b5b1567ccf706b33792b792bab101c4b97d74ef4dc4c1d2f91f5a217d0579022774205e988575a542a89b6e1d2710a6f8f78b2f5edd6517020f0908b51d54a112131a94dea1c4b14e582ab47ccd42da09e5859f42c550d1c2234630637d44d132473e09c6e1c40862f30549eae038bc2ec295b1123857c7ef23360ed9752ba21a4192544c78cb447c00c4954ffe8ca7c35860de19e770c3fe0a134139dc85747477ebe29a905b0d26235804910cb0dab4d67824feb13a7de03ea6c843db8a5613433d763e798f5c8c86a715c422608f77771d01d93e84ab68abbc423a040856c167843b04e82129127ad656af39a416792a9d19d9e4d73929e1619ae0d4b3ac68f4484465d84712166a90ce1c5000d420c79bb90840312c41f755a09cd60f13a9ff03367e961afea4b28dd4b96d47ccd6dbdae077ff244fff0f36a602460370ca1d19d9d250ff2b9636f0aea50cbf894f9b00864039cc2fc5dba7078528e3e2c9e8abaec3926570a11702a5331795a0c8e9fbfed722f7c4ecdccb7f42bc36fb9b2f576374b9bd3ebd9bcbb41de8038ad75584c0722a17afd3b1985c4b8c5c54ef618424e99f927c2c3dc723a111fef4ef5cbbe23a11aaca1385bf279390c9ca81c0b44dac7ff80d554f3ec872e3995579cddf3e6bf23a6eb8cb30a95ea8c66b84d8c7a012842fd7dd2c3cd4b207633426636dd4b91a0e2beef83a6dd444f39208d4274a1924457df7f97e256d4d5c64036841ff192ba584d2b3643c3bfbb146c58b922157dd5fb2d157c382bfa4960d38f04e9c8453edb8cd65f6c871166f7b7af307712597863d27badb8687eb23633f6e7b48d556f7ce0fd1c74776f207c8b70101a8a72a733335176a9ad3d8a759f3806334e0258f7f0be5d53d3d1906ca10794696e2184e80d774b2081a70958d5ab7ff98c07fc99294df864cb3e23115d3162917bff8ae2a7b73af37415337715ca367f86f3c1cce7195517dc576998e8545d7717fa6223ecc3785e5f4de595ee7814d7413a37a78d37cfb280ca0451b2cc4b5a5ec409135f6c07e039e04a502a821c07694d84e509e538269e3f1bf15edb8a3b7a3c7042160a5ad6c797a16fba3a659d8fe7daf20c5e7e4540e42e638c89082e543901d3f8be6a244e345ec8da6ffa43e59f5df8b4a19ddabf454adedfcfb8dd2b57bbfa6c190bbc27346727b8ad9a17018f55ddb25344a86ed8ef695a9ce926f291bf2e8ccaf00d7c7922cab725d15bf66f1f2ff2a51b6b1a5fc1972736dc2f78ffb600762f6e2397b95b2ef738c6df2995e74308d16db0f8a45927d4d35e67e4f9a44e076261dfb09e2421ba961c888aab8be7cb4ff27b53e6412469bb45e06097af7b6633616ddd0b31006debc28d6289a0f3bd911eb67090998930d2ef9add6eef2b8715bf142236e394342f5f5c9aceacd2c13f3039626597dedd80f639e0899adffdcd653293cf4117da53c89313f88f9f403826f280d20a886cfe7efb8c570ffab2caba43c9bd264e1a638868e0a57a8ff681375a6bac74ddcf4057b6443916f252e2ae6abd2aa084b0c5bcded714ab8a142f45c67060662004a5f7b8d1048e7c213af8d6505cfd55380607e04f38baaebdaa2f1df1cfd11f0fb6ba755c7a70518cd913cb03fba0114ba15940c428736f23d1dee68f58c5212beac9d8fe55d7d1c457cf7e2337c567e35a88ce9ccf9ed22a85aab845452e278261a2e89bb5a518ddb05a6faac6d36b6ca2ce806c94bece38374e0f40d13d7045e2cbcec083111bc603e2bba4499a6af0c16ae9d99693219c307644dd8f5f215f83539cd3544463ca5c4c048c4bf94a06c6ed5561c19fa2b372561fdad8d2b1f336c18b37811ac7a6c529538b6a9e981289d31941c6cbcd8d5f60a0cf876b6ea8e2c8d584ce4e594af96f4f09f6f92f8840964987bef2a14c8a0df751d17090c2d1136d4a0a1e7c3d4e8fe62c4c270b1731f56914ce298b38bcaeee760d03476e6137fd8366bea2f486a12735a7914faca202a0c1901c7d8b6c6add399831ee02a428e6d7d638a4def7501e5af1f94fac4fe4ccac96cf2b3604d0bc638741499f1e66dbd909d16f60bfee0fa7f19b432da49890c8d0d54d549b1e4698d4ba3000fd7b6199364ab244a121f4701158483594c5e1889a2ebdacd0706fa3158fde6bb9329d851ea57c2df7548e3c26b36101ba12e348431284f58a6e7c814e31df4cc8d96665fa6be84808310a9248d291bbbd6727609c0a6a7546219ef09a31db7baac4c029b50d084e74b98c358f864a6279b91b7a674c4e618905e78bf0be915bb64b2913c0e5fe102f1fb1a91d630701bd2033684bd88760b83f2600381eac0492e67ec45a199623df27273391511fa9e373e2dffb8c8f81766a5498045f45ba1d68cfac024dc2c42f0fbb97d222df2e82a2d35cf6079e61bf282c4620064e5bebf61096702f0c6fc9d0bf26408a95fb263a0259c697fcc87d7c59cb3b4f8a04eb9f5096f785d65ed32543cbf62976fe428872a2d812f61115c1edf8409d862668c7d4aa300ca4175029689b39daceb8ab28ada39322efc7089ea9c1ab310667becadc38d4727525e0b7b13dc94197e44cb54bedba58b9095a3a537ff2429b197c933646dfd91cdf2744810950916772880db985bfec8a87460495907f76c8528647d5c0df6996c9d9d4095b" - }, - { - "seed": "a2e7e2ae479aaa97442986f48f4c8415e3d41ec5aceae8f7bf350eb96fa415eb", - "pub": "69db904c47a6763f270b088134a9ac11c6f6784abaf5b2f20276daa9af6be3d8f3928fce4bc28facda86c0952c0f6b6a3c9c1b77034f43180e49a5c7e7073a0ab906003e414bbb31d083805f7b4f599efdbd273db266a570ee247c79ab013211e1e63f7f0ff2c4b24c3d0811db0f7092b0f9cb88279ece0a2927b2c402c8103bb1b9fc5e44bab11c7323a073480cbcc25ff8339821d3846a2c5dd6ba7a4d324a7b7eab18120e429e4ef6ca24e51d7251aca5797bd057acf7be551e0a42993bfb3060528d708c3bd6db0cb997ad425148c26b8b25a7872fcc1e01546fa272c574bc2204343d8cd899f04306b0c13097939c4aec658fb1283b4bea960903cea223fa1be79b237e68e27ddb0dd736d24f133751ef272902e3b63414b420117fd6b096cdf00ca0dbf49422839520d834fda232e3965eeb7c676ac79991c0c0bb6d6398c5193af681a72a743e09dfca1afae132108634c7433c4a58efe10b4c6c1532fd3340ce92fd0895a7e7c28f1cfc78c533ec523a25dfef852dcd68af12d58e89e44fc507fd0284c6cb23f13522169c5d5337b8d5b3bf104a3a4ef2fec9519e02c75c7c743ca08f2f0b6ab8c554bc0dc21ed79fe3e5090f3c78d7446443310d5a6eeeaa2b7cacb843b320be45351d869dac21efaaabf419e13266fd9ff0d2bcd0257c9eaaacedab7bee6ff23f89b66c9e5c339d48c01dbaa67e3f9d00c8e4aa7deb788f5f2575151c9bd569eded390d43492b921d78cc2df391bbf73faf6be195303a68d3c0d0c1d179564cc18275eab7c2ae83198b7d708a9aa87cb807fd5f0d22856fccca794ba2c9db4914e789bea54b1c93360515f64028b5a2ccc85d6bd637bae622f0d06aa6e92ebbb45e4fb96904e2d3c9d04c02e75635579155322e0f9c869e7be8e88845f5d07a2193f361c35a281cba881bc415a8338284eb9cc433f51d910ff12fa6a14106fc8bb22bdfdf2a4f8a21aa9cd4f31abaa1f55486acb514463336681543f4645e21e92c5837007051056a5556b6a683ef0a8cbd31b9add845544683f25ac9c0c7f255230728f9b30263dfc43ca4f121c97ffa5d784218f701e326ad0f785deed9c87b89fe0ba887f2e9cb4c8be1bb8a4749fe4dfc363897f6cee5f3035948dca8f7636f80f9f06db48c9dca639bb22603d54301def080df81606eb1fb1609ec265863291a3ed5783399fae999daea7d166b16094fea097fd9107b82ef84b433e38984ee4dd92118d8ab175f4b5fbc073c4d1163da59c774ae72a6ac9208b77053ef1657267dc38dbab8ac9f6f30a20e46dcab3d1056bad4851d2f23cc2ea23fc7dd060e0502ed5631cb3d14f2a684bdb5bde11d7c1759a6eb8cdf45f3ee57af8eb66317266203b67d7e9303dcf2b7b2c88e489eac5b42901eb4127028897c78d4f5d65311bb4cc3694e51617e4868c6d74a47cb5f6cfe7aeee0ba3a0cb07b13731966242b7088ebf2572c1a0292bb94fa5f5cca417257540e93e23f471c8120e6acf3f61f1664478aa0b8669e8da4b1945e844f727a76f546187a901092724a8fd52fc0aa947b28fc12aa40bc58c114d0cddbe70fbb9243e281bc0773794da5b1027ba741269c9726e5a2e733647dda527d57529a2a1cde357f966f5c3bfba4d2c9d8cdb43a7a914f1ea4ce78cdeb5087dc310ff280f2857924b805bafc6bb1b9b4b654d77287a1f8ef50c4c69394f7cab7505273d535c2fc0287fcd6819caa6346ef02ac708cb94d8e79fc89793ce42a7a4621f7373977bb10dc2e4b795926ef5ed9239a7f61377dc60167775b7bff598bc1bdf28960de3f9d3c77ce2e516de68ea6c23a575e5c25fcd8bbd816ad89a205062e97c9d01bcb77b0a07f878983f0ed5994dca32282304d2a3fcad9f047144c15baed2e32c38cac54a8c7e94dedfdcb7dda1b4357de27bb2c22445b61925e89bd68a225bfa6b2b8ccedd63201baae4a7870d409403eff97428d0039d4cee026a5265241f69c6056359fabc300a0718f0eeed739521110d18d038af69d81e27b7e4843249dcce0ae5ee79a913acb291f744ed1cb22929a2a072ae5d1df3f4d162afa88e38dbf9d4e090ae933a683823c3bab88dbc825e9cecfb387f599e2f7f87785959f8354ec0294e4ecf92caae4336c46a187166ff025f10b9dde76b829470509afe07e8819dfd8d887dcf4b823bf9e43ae70cef1aa5e81c5ff242501aa3603fe1a80e4c366a0765c47fdc5243dcc3dc9d20773f07b9a0538cc10ce73b181b1d8ec30bc642ddbfd5e669dc58e8de981eea6edd82956b344c82ea7dc591e77f5f91d718877a99b6d4048c4b89d59ccb468d18a8057aaeb81f4c4d69b050b26e9263590840f4581d9d7b3e2f0ea332adacb1f6d18d41d33f1862b0bdb137f43031b7c4f22852a5ac933b203351da39690b67b8bb208b5b20b0d9649cda5e12b1c3d3512f2643a5f06556353c25c4925b9f81e7dc395a45604675cb97c3fec9fb8eefa2a1c5b3b127b967082d1a30a8fce2c40c9ff19910dfdb83dab299b264d9f8705163e263ed3cb96c9d1aed6504cebcfe23575e8dcf277d31252d31ca28e1bb13fb6f99312574b3ed48201af6916899d7380cc4524cf266a9df0dbd24a92b044114d3ba3a2f43c855e2f43060340ddf8a881fdcc27595f2397ed54b2d1d253a255106856758f7b560093d22859cd92cb8960f9ae219fe1159b4debe6cce0c138ce17c1f954142b174840a5b5650a6b74ce58dc49db7327a079238fb0d1b664759e9a03bd84d01a81d77dc571f790600356b6a918a3098ff9d34e1bd213a7a760ac00a0dbd023c6a68789cb3697610832024d0e5f3ee4b452d9fa621921af4b3c2ffef929e694f8e2febbc4d49367cb90002c6642c40f63eec0a5b98568f609d23ab6595d42a48b5b8de8e81648f62efa8093a225f8a989ee5b22d525d8e8fe3d1a346d3675a9a8923c458f36272570846904757798e71d28fdd6cb2be6c1938be35c0cfa7a947a04dcc3aeb8113aa676dab3140c4ea765f1543ff651e30472280d8e3cfb5d60605b85e7bf7114684fc85b847c5d8fa26638d40f7bbef38f4ecf034d3bc323da5eec81914cfb97fdd9cb90e3fb860149a3dbf22211d1094bc508833d8752dbdec5433866308678326eca3a3ecd4932b3cf7485f32050e1b890980c62c36aa994cd63b9f45964e191121b01c1125a48a7630d22adfc42bab427cfc1873fd0ea31280c95696106e1e7a152876945926519e2368a1289c41a685be838a3e224c99de0b612d04d6f20c86cde51527c276d11c5f97d7934f1b22bf68e83a754f44ea9f5a301b1751d03bd95372ce563884d728ce27769937a3b6d6aa0ea5f9599f1632c8a0ba19d6b3f458298ebbd5b99cdb99fa20e28ec3ff1b2f1cd651a19a1009de33e87b3ada730221a6a140e35a009f2136f8977195a4fc3cd5a66365aaf26d3d13268b3a71d4887474a5c0e24e2998a61e83235ac8fe58e7e613ac24b8785f1ceb0cefd858be6ea2f4d91a63de3553490035b7f8491d6c2a0d54c0aefcf2b3171cb88b0183a36c54a003fbd1bc99ffb66d2e30396547e5082367da888390be3c7b7d78406b0de896c1cde44ef99c5d296aca9a9e425feb7bb9b453a38ed551fe3496cc7a667de6d44c49d4e2c80933aaa25db7b8721c56dc27442f8c5", - "priv": "69db904c47a6763f270b088134a9ac11c6f6784abaf5b2f20276daa9af6be3d84eb9a962889b9c4806e696c73ba6126dd1ad6874d61eac3989f905715ddb6c02489a4f6e4fa1ce2d8fbf3ff9b3179ab3af11354efbea02309557fea0e82075f98c3769f9ce6d7843ee1a5bb4e86d059bf9a1a47be5f1ebc1160bfd43510df97543c449213502d0442a01338e233029a2107203186ccc946504128c4b186418084acba88902195019a9101a382621916510b3081a252124c18552162ed3880d20c88c20c129cc427222042a234772a3007113014c4ca6455c08101b447204b2416110811b3981630261209504839400da26658106701a026010326a11a36c59c6901c49649c328a9a060422a0699b4841ccb22499406140086982948010248d00a02819c24c522064114430e3c081241824e032820b99900c350e18282022042654b88413b14c0c8905841221c8084008024c8c988824494451460a0c3592534662c4442cdb420163100241c44d1a856d802032644028900401c12032e3487001378151164e0a448ac93022d2066d8c02265440429c040e0105402130308b3269822692c20620da82886300101914099bc86c93345201c700a1244a0a0341a434015a206e63020de3922888c48094b80c98c42ccc125212b46d12264ca02248634240512645542064993890a118316308700b81710ba14923c6490c4931e204882139121b406a8b40720bb4296230868c264958167122202c48b028411005d3c04518230582982512848193c0292499805902215b9688a1801021257203966849b2001091004cc2291802011aa20d5014884c280dd0262e0a2871e1146199384a1b2000d3020e8a062a61b20c128765a4103112c74441406210022cdc3448a1a270c944286210659104649a2488e3182dd1a285d30625034132612445db182153b408612022c32630844400639649488410d222868bc80dc2b64d63a88592324153123062366dd496900a460ce200481b3100109809123829d93421ca381104968c820220d988281c0410191550a3946dda322011140d80c660c2366142a624483850db204d2399651984019446324ba0259ab66d13966cc0802011229158346a20070814017111847089448ea3220a11364984328603c1090b37255ba884c0128a22452862104002a2111c210c21382d1130729bb08d949268d304016210281b334953026890c66d22103013c08c5a1685899864d0304610330202024a1cc66410451210818c493605c1428984084614c061ca226a4986452093685834466400454028618ca4901987515c844da13470d12868a4322604b290da388d02162d2081111c3066d846495446810338494ca425dcb284584266a3a621101328cc384863b6516102895b16251a9084434849140101ccc881e102414c462e18498a94226dd9968d901061e1482800256c04806d90b4005b244a2385400c332504b60190b42c1b198158a6499ac849e08640e0182e0400849b262562842d9a348861a680d20845089531c9006022850963088c12042c00269153a45098920c1ab04983884de4340e50466a02c66d1ab720223866214041602482db307184260a600600d0400cc43460a3206862c47180045142a8244cc48823010801c46d61384d204482e43432e4b010100484cc388d2296658ac20082126419104664108d5c900cc90480a42225a200868430065a42698212821b47115bb28c11128444a41014286698066804432662466593100c03253208c50c022162834821941486a1c6308104420a80815a32056444524982690904682400821b4848d41482538224e2c4694b80298a006810b960621289d3c86814203183088492224d14446ce2c011cb8429190326c0b260d9c26d21a52024122503248658c050a4168ed42410112209a30062c94666e2308ccaa809e4282e5022044c8821cc2682ca400848480e1120490cb731c1840910002282468e4c361221a808d188249c148c13138ccc964cd324484ac891d2a290238540db2232090005e02686cb108a82388249a630c24865e330624824921ba86c5bb230441024099581c8b00849000550960520b741014451541232223321dc448a1c23205ac82823324e21970122367251b289e214091921601b206813c36561887061b6051a204ed2129113286a494606a1c60d8942121a232c6d5cc57047e287560ca2baae58a9d3d4af4eb7740a5b76db612b3e649096fad858087f3aa5a72870973b67ad6ff3ebf0783dae36426722801cc1f9a3fa20c0d79d5aaf4729b1a02f5412f07f86da21b0ee6e298729fb403a8d5d21e7c621cf10f9e140386873d1b6535406bf0350e5a0c7dbd7272afbd6ab5f6a5cf4f40771b30adfe08ac43a576549c771b0ffe3031eb8251241a1005d6525dee56b4a7eb422eed05f8a101780268a81c3bd80f52af1f2a2349a18c9935d8c841202641e83069c27642eabfbaa360cee3099a0c109597c69fdda047a78197ca8d6fb96b9761bfec8294d96c71d9f9758c6a09f733d75123c25a967105d1bc626ac00f88c5c30ecafd078c8951366fb982369d7d387ff42ec4798843b7e5da6615d42c0b2929535015fbb4d5ddc8bd645c5cf999b13d0cf201d9d1d4bac4b8723b5b352d76973b0c7e51c89109b01ecfea0f46eb8d46f0af6f716d11e3513eb04a111504f0e867fe5d147b43622ab2d5355c2dcebf5476da7a2206a3795dadb6614c823a0704976da51c3add69e9650fd37d64e7e89e9d600c891bea4ca8d98ae5d416e8b64cd878fdb25681e9bb7742aadab1b8857528a257e4ebbc7bc797cdf5b5746329c2aa2abffe4a0375ce6cd052f85c8a9932cccb1a3d5c564f63994eea4a9567dd161ba6eefe270fa8b26c18f5c55783b6591e11bd8cae96388eca6bf58d30fe7aa0d35c2c758c4a23a298dd41b6a5dedf205a16da104efa609f32cbe2dd430efae466213a93dda0e71ebeea56d5f4e589432612e4e84289ee7017de125e0dda7f1555cd8126485d34d42e7e5db8678fb7ec00dce719c1a2143e7cfa64b35da402abed2bf5a17615b1e86207e4fdea1f8f2d89261156ab9b6397a3c309e19595281e4bcab3f363bb4ed72c9f831c864cfc65f88a9c143e26c932d7f3afdc8d8d4ae0ccb5fdc64a6ece4869983207d71e1a7e7a87eae314135dcf923216f741f34ad0919e6e45d0a6a4af35ab5875cc939ddcb1551859a56b61bae3ed7c48cb1696bad72711439dd9ff66d067c4b8ffcae39be5785c8e4501099b073d83d958a2c6c788c825320cd3ecdaac9cfe8f56ee21e6bb25bb2de00a6afac9341c9a303bcc88cb960fce330f8a2db01d172e5e2add6f2f2aeacb8ee6152bc1e2959ca8b85631f05a18005b41df4acbfb9ed676f5f83a9948099fafd7959ad7d75cdefcc52324902393bb3808f384a9e2ed1449bded7a958d07b3685cf9fce4a0d9fb59dd98fdaf1a8d56b6752fc8eaa13907ae7a5e6dd5c220e553145256b3073a41ad7cd2d21a8ae720f6f357777420653bfe0b87635b0a86a5d194ee3fecbd8ba23af715a9db5bf356db29c6b48a36d31efa9261b328349294d7949a8e9f9945ba56895530006e43c6d368e9730e0780e691428535a12d89c98680e106cc5f52de166cff27d90a495c46c47593c5464371c30a0a8f0dd9c4499f534c12467bb2d0f118e605c30181ae40fba9a8358721b93214c7c4c27d76adfd0cf97e3449a76a34d25b15984ec4cc0376829adff7cc57fccd00d1e2d9a0546210efb00fea0365dcbf277a692f7ec9f64d3195bfb27ee14a9648ebae2d83147e4bec56b2c0bbcddecdc563e24d8e3374750e53eb201621b0a90e016760d0f9a680f92c0ea259686864e776a09e300652d608af5982501b3d0c376d12abd6e7b4a3b9ab4c0ae6ea7b7c4aa56a6ddbd048c6abd3c1ee570f55d4a4ea5de198ce552d04b942be62d88366c2cd5042deea27b3715b03d1c20b40e41f981b3bddfb8b35b639a7115d5febc530781cc9694287d58c7f0f9a6ede15ad13b6d26001d697b3a39eced0edc92421bae8d3b236ff337e255ea3547581639a3be424c82e6e3191303ea62c06fe2b65edd584d1fd863ce325dd5188855a958dcb4600e6f2937264136d26971d42f68ec2615979660303aea3877c7e1fcaf93232af9b69c204bf8f7c2683e3ddcdf880428e096cd9eb71452013d2d21cdcfbd9f38c80c25b3768aed3163b3146ea34d97cd94923e5cc07925dcec98d1f0011c2803008baf6cb40d589a532ac6fff4c0defdca537dc6b0fb5e11929c4ca78a7692af4e90a0a5c2248b26ebd2992ea16eee7fd0171161d0c6720e06885e8baf76c17be2d0c2192d509a3345d6fe4b913d77063710043a8723f224e3ada330d6caa2d84eaa0a6ed24f58ccc617c6ec5a62aca355297952113da5e710e00e33dda9dcfc40a81d09759c87b59917f72b651de0613c903d976af2470feff1deb3db1aa7242c76c8378afc35b43f28112c9d369a83f98d12b7c683e8aca3010fcf4136f0b66e28bc5202047de25eecfd54bec95a72fffe28f5b81a3beb2721ef5acde50dc0e4491c40963a99a2943d55791eb0dfb6b23a5bdee301ace97a6dc07841dc435ec8cf0e48c098dcb12b0342c7bb195967ffd55aa04892a92c5cecdd063a761ba99071a5f952e0dc693cc20b680b92f28e90f3d38bc40fe2bebfeb2b10307671dbe1e221813240a6f5800b2e5baf10b6b1e71baba0b1c5e1364da0b52016f6948c8e21b9cb9ec0baff49733da60321f922b6f1e834ddb1cbf1ef3855707b4f745e037ac37c4b11b2fa850d1a1730fa07140b138a6b65ae645d30aaac16e423fdd339043c4afe1ccfdfe213a442f20694447e9b5f020bf836b43954da605528cfb3af7655648ce1c41f1d3502a2f4569862cf8ed8f369300b7e487f9cf80222ec66253cf47e547f621f150a7099af78e335e3131b3ac2f9118a5aa88954a07426b243f9214f5d0a5c7ebfb400dc1459c662ac33c063249228bf689c4c72c48db11805162b74ca1b125963ecd1e77443c86540ee617e646b3c623e724eb7e87359b84f701c0994e520709a20d79c1946521da44914e2041592baeb536239f313d90be1e3eb51f70867ff4830c807fc5680b378b475d66902b50be36455c7b9f3b3b8dd38c82597a66568e8335fef87db6be5f522520843e9bdfa7a20f3a4dd7d4d971b6791e1993ed9c8eaf3b765f0dc9e64eb81272e879a3cffb27d6d749f353cc3981facd9a0fb77617b67c494b5ae0ddf6a022d8ef9a71a27fc9f8abf2f0574486625382a47a38c02b5dc56d45e6a09fe520eb08c75a326d6c8eea7ce2e97efa656f1be01687cb3c94ca3640d381390076087c4ef93ef5e9a95a5e0c30bc935a93c7ad50e95ceaaa6cc8a0fb25f5669edae60b89c5784f53ffaa6870978cd7846e881f20060096c46837fb5f7292199e5e9bfe73defccf1c7be40e32798d26052d47d232f62c99ee55fea0f4c3ee6e0f885c45224edff52310119a91eecbee2242c462689cd7193f5464ef2db4bfcd311dbebb553e743071a588b773390093612e386cc4f6ce0490bdfc76e65fe807fdab13d21fd4c051e92540ded16694f5f4ff15c9944dbe3e16fbeafb5dfb6526aada096e6505e9d7acbd05acc8a541349d6c9d63ee97bfcf9c86ab745d85aa989a39e279bb969c978a171b213e67fe5512dc29cb0e7a338677ad99888a82bdd9c0fa0ac8fde34fbe827b0dbcf7e1cae9813bc0dfaf0cc3a6df3622170945a5abe8232e9320fc6171f4d2c8c3770cb08d3cfd2f6c965213d023d3bdef71fdea2de7d7740ec53583c613f4e0550cbc786262df425fe08ddef346714511c8a894057b1044bbfa190f76c98a86de22bdbf33c31534b4fcef57401d16b35d0d3f6c25b4eebb4067b65be6f487d46e5adf969439917db437b0a9cdfea69a469dfbd529b9884197e2bd4e2fa0b574d240e53090934e77602481c8e2b3187764d9fa58bffe82246680dac64791c5892f4221074c1e38c310dff2de7c1444584a3b491deb23bcb9703f4c93155f3229884e021acec85f2a133775c25b8a108fc51f8ba94f80893e0c86afb494a58df2cb3c445739386a770548bc0f4e612cd4722c6c46ebfe0a2cafefc01a1c5a0d99a97b8a5f37083f0c86c2968ffc1e68b3be9eebd8dbd851fc9f29d569af12569aa62873a114bed8f29e5db3717d53620f21a42671eaee0ab6af36bdc54454f3b083e6351760a328eb501a46e20d6f310b001200a30d76041cb7b38c440d7ab561b09d7aebb2924331757516f3debeba1280f33748739e39efe7be01a15189a399c5a9ec7d290980f543ae9445b5c29850e02ec347106946e66c3bff2daadcc4b0cb8c02dc80ecbae0f400cf80b4804210c8c1149c9778302e02a17714675d7623cfd68b8a4f26f76ad7f2a0fc895d6dd05ffb730304cb65caa1324cec71936d8b5f5c7d67d9b7de18c05ad788438b557b37ab4e32335d8914452140cc8d7d43018702e7da01e74e313c88256c634908cfd81b276b7fbdfbd8c9a21d3e22734da9a7d0e91224495631b78dd954ede62bba778743b191945fd67a0b1781ca4cd7b22cbb0da576a0f1e488ea22eab295803e94502b08ab94474e1b76aef74abc8be78caabe666fe367acda7e7b6edaa23ee1694d5fbcee51cbcc93528ee246cf2ca38d1466894ba0e4bf771f0654644f4d8ba454e8473ee1da75253143dcc158cccf66767c0af41193bcae7a68d4a4f1f51d74a6542fbe6cb5f61bba66bc15305cd72a487c7a752f97d5a5ab0340373e369df203e1f42298aadb39898c44401826c258271622ddb8c3e4cf10afe32aa2074b66e12859728bd080fa5c3c48347744807f40d96db9b26ebf38c9fa6f44d03529338a46616666647" - }, - { - "seed": "19a113dce0bb291f3d9c1940eb17961039263493360d054d7053837f415a5786", - "pub": "54d58a43edcf6fc4faf7a36866e391c4c1235d5d1e17d987a4c566a7734e552cbc6daddb65f2a126f2bda8c8cdbc0cc3e39eb10b7392f1a9d3b396ff3e4090c7629396074a15001e00c633daa932614e869d19e65f1b1251bef3c4d06489e091a182b14960660e085d7227414dc3873934d394720556d940cc5af9d8edc0c46d3e76aa13ab693aa0862441cee39bfe3e5555fbdbe93369055e010ee6be0f8e4df69138ce3cb7079f0caec4e4cf662663593c1852fc5c62ced1ee1568a365879898d35fd5a0d7558baa86082c5885c30ad7021cf6d609f9fd40ec90a449e914aab04f99a262d69578f09b5779aeb8155b09cacf737688b4a306f28976731bd718d47c10dd349139b05513ebb3bffd9bfd2f1fe69865a966060cb09518fd8bb3118795445bafd95766a5b4a9f785dc6e159c8860bf0fca07b08a1d1bd7287d44ff601d66487aacfa8dd97d1eb12e4af73c835858b861d8ca065fe82d5ea4f309297ec720a9a9d9a17d77defe45dd81758f06eda99299005be793d76024f562b1745d564eef37478dff64c4e1afb9a46c7b02af1bb2d42a28865b9686f1fc9704c48fd41c9f25b15a76e4c9f209180e01d4cb2e2a8125feb664055908ff221aa2696c0229fec0ad48da5d2940cc1740f48c739f9b085f82e723255761ed98f27464f3b1bd9c3a1d2e62f8d6e7c6b543d6418de2a440ee3ecb75323218ce616e02b67f664714d22d16e8cbf144d374ff4f92cc1167952a4cb61c9440624854c31778fd7149f9f9bbcf985a960eb288a3c84cbbc4c0ccbe79661afed706f0215de89f94a696f0477be2322bce4c4ab0f76b1ba67acd8c6200b90a219565f8fafcada670bbda889bd80d6febca44b23c1e58262f7eb0d9af73def2605857882fbaa02e377b4fe5425c305052b7d90b9ca51e4eb70fc432ff6e8eff904fb15a2076e5a3aa4991672053421d2771b06e9d491cfd7fe910b18a03c8f8825c6b8e8a5776cf92aebd6dd87625286acd4415c005ef59a9a464359978ed7d82c01f1c3ec9f9c1ecf993ddb8ac82b658d285fad357b4c810f93fd09751d14d5fd54b7f4a052724c245b2805185fbad1e5240a103cfff4d23553b832a89d247e4c4c607a23824abbe708015b4be633f645bd7a18ae3dbc92037158c0e8ed3da18d5c1d5f11b4d2c05091322fa4ad53f15895fa27dcaccee7a6b83e8f1539532b21c10891bbf94daf8cb0d30af24989018d8098a2abc78a9f0177d853bdbd3c64f15c1da0483da350510a20cf2fa3b8976649787330822d3f22a3bd4c807325741e93101aaa24ed40e7f77dfb93cacf5250bfb64e156d70fe1f9c83ec7b314f955e65ab35efeeb4b43e72c1d9056770bab60b25995bd2bc60b138fe82d62e6ce46290e7d7cabdc6c8affdb5f9b2f29c2c3f462cba9551f745124cb2958ccc41c1c387584b3379a067c77a0d516ee869ab2536fb6948f8e1b7e80752af25d52bdf818a93790a8bc04a87336a61e531cdc124cc984b2ab3468458fb30da44e3b0f5e68ebbc885ca1e8fdeb3529fccf354d6dd2e7e60a530dafbb771e5d340915c526799192508072fdfbb3b4f7db68d5cfc900c9b3918b7bcaec2643d40adadf46b5a99d7bfa03bad27cac1ddcdae15f62970a66f04f793b76c8901269a6ec78a8a9180f7b0e9a253f527ad18287bb2a5b99b49654ecdeb561d0f9d99959fec63886b509480804fac174af8dea598eaad3ceb27c7465c8a332d27f21a79c882ed9b4a29d7f47d60878dd23e1d67c12597602a8fad8aea8d6d9c97768adc033f7181fcf6510c983f391f83a05a4f51af83b0b2a3c52a5c69f3ecd76794eefb3a94c8748a402a1495f66e0bd62290229ffd290f7a8afc09ae115560b86af8ca42047153b5febd823f16be0ead329d3c172d919c4d5358143cff2d7fe631b9f78696e4b6975ffcbd2361310bfd79b6c2d8048c5ab4d3dec20850049555bb3b77f23b952de317190cfe44dcf93d3d8f6e4a80eef72b9e1d16f4dc9d400c2e0401d2f48caa9b50435fa10bbebf0db8c706a3a1212f68f095ab806ee0708ae82f01cac956e4fbdebb190492b15e75368158f648f27463221d44a9f7c4627ce4c14364d4018c7e2c038b93175f64d53acba8ac10b93003ba009d68a42336e0cd805cdfe8adf2f2a0430677940d77fffc8304eb42b1bc625b7f0334b78ec1b0ea2186c8e0af27aace6a286721f7596650f6cae6cc695ce7c3517a63c83b52e9674dc6030ccf52c4e97a72d609748632d701a6fcd4b2039d6ae2ca9d471b271bd999388b33817f0ef0cab773bbf3d3eda0de407c14917a371399af267e641b76d40698367afd960fda709c8272f6429e9c095f1043e22afc9ccc9ca8c6a00d1b9bb7eaa31b56ed14f61f28614efa459dfadc31701578b5befb0886fd0bf1eea8e7170b2278d3e3cebd3752d99e377d180aff5ae5e3ebfb764241c1882a1b980d3a0fbb219ef2d4b98ba85e95d51080be2a36612a617c7db929f8af9ac20cc60253a8404e794a471f2f2f388c676355bbd7dd115c304c8dd42300a1efad1f11b78d0623843e1a25952aaac215a3b10daa5849dd45e1cf3d7a21339978968961cb09d1bf9d4dc60a435dea93480d4bf5de62a234f91b1e483deafc3fa79c9b45e1c5cc3da46823cf549e9ef8efdea01cba0f9619be182be35b5d715ae97f64ccb709001b5775a672d31a4201b2d35de0365097ca1aa8e0a15f4dc04003a6ae336b630be44f319b12c68e39a6373bba71e7d24b2f2bc524ec9b7673a3634297554de599ffda5773367e8d20fc38e35b6a92440d834f05f299c05cc4c6a60efe19d14db8ef3c94f1dbc8df6d415623c6c5e769402b4cb8a7d5635a0fab8892f2318823d3238aff5dd68a54e85258e62dbc704b1e647b5ea28f4b488bd41ef47230b530c4d765f26f043c6531aee91f0c17592f9e0eb51378a42d3fd0f8b1c4cded655729ef5ec6c17c1f3247221e6879d15a5ea54e5e3b338dfa2246f13026e3bd43376229ccb3bd32766cbb13bd038e8c8ea6447a8d54874b745cf2fe48237d388f8358c6b82c1452ede74503b48034c1bda84c80c94e209fdb700856158f1cecc21756acf5124a619fdd1a526eec8b3b263b957cd574db5a698de5fd8bd6dd772e432f96e260ba5e1ee29e706c05a83b5afbb808785f2456ec4ffd64ba1a87288912c418d7dd7a778e1762a32148b4ed5c3f87213307bc9224a3bd70aa0aab18963f000c16c2f61bae57f90b6b34edbc28d783bf1749dc95730e5e3c2af9df48ba51b5226404c154603c25a8d832bb99f602eb9ab0f168e3ca52cc3a12d61df31557ee1d898e159611a4cf5aef14f1e7f035bd695ada0a4b59e0dcf5cffd2c01b7694c65ecf816502b3cba05bca2a4fc7231ff7e79086895bc9dc9f771b66a43548a87f6c1464a27c5b491892ab90aa10f4e3adde3f7d6aef2a3bae9c96789c7ce706b87ff5057d73aaa42b2877802ba7e67c9f8faf5cd692ca84e899305771b6ea2934deb16371c848277532160a66336e06827f991a37a63ffdea3e1e70206632ae4ae3e3f65643c314ad4954c859ce7c0329c52f79e7d601a97853172ab7270176f01912d425f41c9d25fbda66d2af038d968d7caece2b0609a6fa56a2a8e79c961fcc089f26a7a16d78e3e099", - "priv": "54d58a43edcf6fc4faf7a36866e391c4c1235d5d1e17d987a4c566a7734e552cc97349e804231de76b82010ddc13b5de0a751d7dcb16c5c9d07b43cbb3a53dd9883728aec9f3f4bff09208b9fbdf87585b7c55d39495a414fa23a43ae6e5b18d516efe21be6798366e253cdcfe4603da01dffe33bcbb9664c60e73578b836a2c02b73004a3704938021a00848424508984451230049b9024e4440502c791c39230c3c480e1b07108118992386840a888dc866998a0444c1026d4c46c9a104a08c24448268e0c08710ca78c908491100166a13052642464599441632251013721e4c67014b9055cc4689c342a63c68d611404d8c0290c82200a000a0899600880501c004e90a24d0a327148b61183b8314406514b984004074808b721a3a42901252114490e9a88480904404c9228d3104418a929da14669c96314b824c60848d5924124a363088a47004a56188968819b62583c8905102320b956d1c91201341850bb88011c44c9b324614c410223892520628d9b66c030602c9442a51a8100bb06508c191a20429db40928cb42d894248508285d2b62ca1a46cdb440c54422623c8682306668912212028869a3060da144d89c401d930880cc52962a86d01a61151a68d12a21162b44189865152c4216204510cb48c9408008a024e63428d4918420c112dca484e98b24594946ca0204194060e0213801c212d40c84109144ed9962921004609050989402aa3224821a42108158e0a810124c529149765d8388020198a4aa00c832892a22828e14230d240045400721b922523a1682084485ca09091120d891085040980c9040461386442c02c202211124261423000da30229ac02888c648caa8811b854c81988519022912442c50c00844c24dcc900d8aa424238651219724193629ca068d5a28608a060013b740d8804c0989259a346280020e92444a21272a02b0406428481a132c6094484ab26122908d519408a2906ce1100080240100c9850ba6290c976dc0a204e11672a43266c93685123889db104a04292623028000c025244122cb3028e1408a22178c19b6211a08425894510b138294c62c10186de3066c6000069208059134658c98519816401b058522802c42b40142906550a02109490adb360044b88110144620894818167019132dd486214a284061960d51c8911134010c80040aa5491c186503162c132544089160d3b801a4a62d91804508488c1405919c8825d1126452824842b2801c06098ac468401804440481c8b84802434552242124290c012905c1222d00274e9c9070e0349200448a40b4501836655400919ca069840401141262c906421c3128a1963110070404a8058b223124056209a80960326dd1062d049465d894001a150a14129211a781c04009038049a2a82989c0281ba40d0b9150c8b28480c209d8400424026181144a63409113868824120cc14848d9383020476a4ca0044806021ca52504096203446c88400c04c90d8bc89023862962b26193864c0346921b486a90c66d58964c1280919190258122080a2388d21465e3426a91420423c08cd4b064a4143290462413a950cb304992401123059022940d0ca08de3109001a2050c358160c6480a8090229791e3c0640943829bb44489028004b34883c669093150a2422a8a3826d846629ca829c2224dd23620e032490a278021882040366662286263482188b2510c3642cab2450b192e14928d0a0420480628099785d306815396501b1191809220d80080a23669ca320c13800413a64004a32824137214b9509a928d42322818a52818120accb84020164e241729c308444910111005309c14811330022338240a316224c12c833202a4806d0198451cc30d59902444002902b865599685820431d9308c5a462ec0c86d144772c09221009230d9285113262e8b9681834068db166d13105121868464266ee4b28814a30d824605da880d08010cdb060902a82961902919885148126918494a09b78842166882b2500c8591cc0822e4c69110b360dcb07123a331023970823040c184100b246e0c0685cb326e4b98609cc88122b34144c65001353209805009447024a70512410009394c58264d2113090494401832454b8420902831432610a42026c3c40183108acbc6051a266a1432421991299b120d19808410062ce4464a0b47460219046230858412129a34655c3e755600052f4f3edf5c5916b41dc05f149e184b1e666ebf7f765dbab48bfe888be826af7e8e99b37824eb0271cfd5190110b74a86fbed6b09fa7ad5ec0a97279dcd655ce9e8b850c08e2bbb2d984f1c7db71985703ee2db8f5a2a39258d5995a2307e49a282ce70f3f9311310625461d9f78dbe6a5af05871e0ee91cb1ebefd4af2a0f5e186deed43873ddbc1c1b5b16f9bd28ec49c0d4f8b6331d180e897f9e57e91e8589207ddc4ee72332454dba9027d355e80833770ba5569831a0b1f4476db6889eb02f4c287487961262f2763d90c7884b8b73bbe2842214e7c1ba0a245aa9d2ba1fc4084b05f3fd83f213839f368d68ed744d12d140e242e4415d041a56950bc6a779c39389dc16e0af212fe08065e3773e4cefda4944946541f26d37a0bae1a4b0a7a9e6e642d48a9beb79ae11ce26b2ef16e5d8557c598cad7838d527753d083dd433ee3d902cc6051d898fed2b71ed3b0d60607e529ab3e96006e66c79314adb188fd0cf0b3bf3cfe28e88c4319ea54719746514154855165125ec7d520c993b35fe05513dbd597c349a1f33e6777c039045f57e0d69b64a9bd1d44bfcfde7c42252e37dd5a0bbd70936998be258bebe12bafb9e74cd14192e43bcd8b9180d4a5d4395a1171973d92e5cc70286b81b23b7cc1ec231b5cd6eb13c56b19fdbfe3482bdc677ab43cb45d102cc2d021d0517a836191f74570882eb028d6e8922c401c27d859848b124517da0250cc4619aa5e6f24158088d30c7e1f777a266ef0a83cdd22a2c3039b5b1bf0cc435aae6308569c86114de93c3511c9f543ddf8c772fc5b983c1a0e164a6153064b2ece0362170adc3d6379830d1d536c005aec9101cd2bb92c6377a60f688040a1ddfe2ab4d1c89c02c8572149f9a74b0bec48388daea21ef6dc8c70216ebf45c2fa2d8f8dcc53096b129f1883259b9f2f6cc27497f0a5b0801974b5b49be50c2122f5b8b35e29c3d84e02257948f82ca0dbf6833c99fc3d7187b3eb4716edddbd9f7088153c1fcd7d85ceea98fe260b4fe645a2474c327c0c6f3a28bec66559cfe36e47c0045d365e52cfdb96381feb9315c409329f4e914c06a2302591e132c0e785be1cd7040ae8cacf8948935cad6b74fdf0226090ededbe4ef437e158e253c3aec04dbea34f17ad299adee0fd7c837ea2a9f2cdf0a4638c8b82af377a6890c5bfd3ad45f6a693f8d26e8114f42189f3ae3c190c0e17ef114f8af8b329e5ce57aad5660c3b7219420b55070cabbad94f1f6fbe0f41c9368ca6cc32e9ab028f9e867ada03b83f4c1d90fd2af1b2e95d219f2be0b5e842d675b43ecd2770321823b817f2e037c0e2730a55e0ec202e39b6e8befffb7e0621a5fa75ad7e72db7ed1c13bc0f7ed174406595130bc3e48592d8e77e57e1c8129eeadef56d48dee7fd5be68e8e3d1130c4ab988123759d9c99880f9b528b47705f5b9ca72719c0ee052007dec7b2ded60eadd5c5a999e9917fd7e088b43e88056d2100fceba00231a12f81588b00a4525e1a8f3a8e04b8c0cd3b25bab44f30ad6c8219d87f53c43d724e41a7fd339669d70d0f7b56c0fa10cb4103a2b51c523a3f65773facf0b41927652df5db86ca7697fb3ce8e5e6ae0140e0439c178112f662062777cb6b20f63839ed5ce729d40e85354f4ceedc64f12d5037557e1473e77282852b317648ea6c0a7cf940a3e5e1003c2fc5a161b436fe8c79bc2d588163cef984e85de290821f4828e6f0e70a3c51e8b71f37b5df84e01985e4ba8541191b72860b11fac170b958f41edee45ad6bb3d35340bd3b4fefba8b5c6cc7b058fd7aca8efaf7ef900ec0f64124aa5d5508831880735089853ff4b590642605f6affbcf595d08431bd9fd22c3418c09b1d5a934f07969f2119fb586cbe0b25e19f76d5f692c4c841bd7836260dc49df4134e0369b1012a22bcf6224a01be1ed0fcfc75f98bf35b862a1a687117d9b90d1b9750c6ab77741c01ad675e7e0de2d7338e9a31cf756df4b2635bb0da364a807fceea58d652721e6fd90bd9915bde7096c17d747792be8257ef96bed78161cede0b9d2f9bd41cf31f03dfaabef7995b260618b980b44651f445ab9a92ce9b298c29a32d13dfe858d465dbb498b5cd28867d5e41cdebc054b6e8f364fbf76d4e20d3a56f0feac48afb6580b2728acabd70095af3a2c3cb2d8ee1c14ccf4fd3f189a571314a533ccb2143b8953881461f1964e491ade2ccc832b74dba7355d85ae5fcc74492a7ad468bf422cce18fba31d5c659c34cb9dc6deea4a4912df56298aed2a06504d008da11d7b6bc97c479e06deaed710a31448a19bd874ce1add8a74371a79524bf0038b5dedd4cf7141d94ab57fd7192d12673f2b203c2d4de70f752d0deb53cc71cfd6d49a793295b7e9254ed1a489cfde85228534bc3de73e363b89aca2230559339261e7f8dcb16081093ebd83323aab4d934af7d64c779ad7a838e862fd49dcf11e660b8e01b2d4acad28d378cb127396bcdf43e298ab16690ebf9b697435f7f932e880f70324f753c2b96d639c9e807bf9074723f2133a811f43f0ab15d42b85691e6e21f4d469b8200eb47cd0179cd05bcebc1bc0971c8030985b4b8fa6f8c643680b0d3b0d01ddce108252d140da27f9497749f195d86a525f3504cb21a8d54de291ee7a3d1270271230fafca6cb218a0d13d0da00d37d1619ec2df33191ba2240a17387023e3be0a3cca2a4a0e3780b09916f26159ec0d43f8755c5b65127ae029a8ec088819b06d7066b1fb84d8064301ff88435fa7ad022c2f922597f0db807330fcd5f385fb42853a917e2234991e589b3d7327a40fa0ecd5f636083ce8baa1dc8cce430ce9544ac6cd5a4f3c29cca632919f0ae87ef62d0e4bc118f60dcb5984b2bf75c433acf52c8f9034ccb9b2ac8e914b819c868a68ceafda2f30170eb63d7b0805dcc84bacd77f01a281ad3c3301a4e2c8ee91d5c9a186beebb8f703f176cd10aaa53cdffcb46702afefb4f69c931a897e9e5fca80468d331e90442c37f005ce72b9a79ddd3df19a902ea6881f47e13bebde90c158c4b43d27937ecc4161b596fd026d2957d772c4e445b1911933e58e72c628ef7abcb0e386706ff4f399f3e113c97f8a5df6a42540d3dc0c40efb76fffb0cbf402c04ff228915e405dc26af127cb93efaa83b5bfede88c7f6efff7527bf423d0cade2f2421ae2da4ad75d1a05c5dc1a75718abc91284bdb5b7f38600446e09b26c77944828cec8d7d63ffefe2c31e7a20f43135db89d031c565df5d043c77fa8709c437fa62c7cf0ff5922a819bf8d4a94c024444bf905cb37551a186befc3b6350bff7fc65936a5c40ad22b7089085a7374b856998a61808502834dde31a0a48bf200441b9edee01f5b199e6db07a12dd834ec3dd367d73a3c52042cf08ae959ac02c0c58f71a07ce9d459e92a56d98203b1f01720df426e658891068a92ce81edfc84ac9477bd6a2192fd5e79464e08c93345f3e826b6b7239bf7717769bf28898119084cb90e571060cb5d47b447d6e6dc88e08776fa3eb738bf41a242ed8d49526920ee849270dfac87ebe86a5560a5e102746f6263e6251018b936ca6d9d449b435d8dc3e6dc5c166be545b1b21503a2d2e44fa0e6dd99ec1a5978dc44dd6832917b3e07f815297e546a4fc5d245881c0f0e6a091ad9f3db12458dcc7e86eaa033f809232a71a24edeb2e85196fb44b4fd991ce017e028e3e6bbaf6a2ce204348efdf4074a7caf8a3033354f8f26396824bee9ae178df382398909bed91c458cfb9295c2ee61cbd4998a22784e114e2438f5dbb68474f9a64afd78e1475587e3df30daac255ad5a32abffac8e3f61949c80916a3494d24324ea1c4998175594881dad6b3dd9a7c3dffbf28f222eb2519349c55c5bba6b9786a04b0194f7e5be99c2456b1aad499456da6268bb3b3ff0ca78e96ae89a6f606eeb740465a669cd63c7579e2251f1670a51a0ed4ada75b6475841e831ccac88ba5e83808db0dff309aab6384d0729f1893f62aa1a03b01ca2eba66aacda0a2f8ebe18ba3c9b847ea99c993bc3c17e787b5da8b96133a0d27f86fd6e2c26106c23d1ebcd4377c3c5820b95b8ecc273b4ba8b7a7309305ec8c1cc8ec20b3f68fe562cb37e62da4cb632dbf225aa93a0de95bf8bd29a5885dc803408d98408c7ceff6315e7d7f5d69d75b8999ee6cc221fe6a0f62bcba373e8cbf32e5f9b62857ee41992e5dd8459fa1cf0f6dec3969c634b882faa1ffe024df585948c889cecaa396ef6de863e02b436080cb9f62b6c135da67a8f4fbac2acd71002a398c8363efc1309afdcd62292f3c633215de78aadaa4a6b1c66c04ca0099087396e99698c136d143d4ea29107ffa747a02bd68d725172a92d1db3adfd262e44b09b936f1fee41bddabee39e584b3cf89f9acf9243456af32775b03fb8973b5a4a00601e6ea8b9dd48b922eea287817a7cd8c90698133c747e4b88e72398296aed4e9a0044bbc3cf9ece48cb595cc9904116a1c83df1fedb473fc95ff777a33fee14d8fa79fba19acd12dd5df98ebfa137a14d86955b4e4a83ed872e6759376bf9c896802a283d048135029bb837186da5049f3c02634a5a649ae5533b8dec031dc94aecfd5ba2194bcfd7cafe51964d4f6c4cb83aa54560dd379c0c19a6cbfbf2c9a96474573833a97152a575e8e925606" - }, - { - "seed": "3920dbb9fee90bd5c3d8065efbcba178362098689fa311c5c7c28a99276bdf08", - "pub": "a46cf4523e421c0d7d3a8cbad5240dfeccd41d6b9a1100a209c25df5bb226b80abf215628a068fe3bfaca877ede0edbced79cab0de11bbc593a462bcbbf28871a6170b31ccf7e843c1a5b8da68bb0eeb7f7419fc4621ce7d048490fdea1fc5be142adb5f55cfcbba7ee5937fc9c79c008bbb6f54cd5dcbec12122c705649b49678b8a32f6f32463a9d01585975fd18ab56385aebed02b029b5acbc22579e0ed60d21c85601deb097d3629160c9ba89e6bc8f1cc47c3e6d5ae45a40cacd6e95f6ce3f4fff5c0b70d60f00a267b4048c7a23f830451ed7d93db85db114644d931f3635ea54c3f4a3b7c07d41155ea2c69aa77bf327e68f6193e8d735513b2532fd366dfddd546141a89c41e25997786ff5bb50277fc1488f6e18e1d1dba6aa30aaa018a0ec5d14ca22a8679a329692bf1033a0d76129fa87823a20bec06ceaac8ce899b52f0d69c48e123397f9b80b697a7f9ea812093902d2eb5a1f300896403a82f6db6d5cbf5dcae2005f3f5df85b280a96d30bcb0dd79a17e147001814d90f551b8ef4394526cd339336528b86b22e984b506951841dfda2fda5cf7417fcae06c578146f4445839ce4df9c3fdf13d32a2acadee5eda665e1709b2b82fd1e08b657f649ce7c5481adebbeea770b5b2e471f11830d93652674c22f5ac825fcd271c06266d5b94aa7d8d2b0eccb233fd2724b027314831575127a6cb34c96d1ade2bf2a2c9b38ce904ff53fc212151586345e2524cafd8691c58bd19eeb915265edcbdd8ca2870a7b074b6a210a3f18c12e10b62a4695ecad173be5067ff91d38c985932ab7ea491dc925188282bf824f5e9f7da7236ae98d06a731bf0c05d4d8b435004a16a1b60686891eb80a41285efc61b7c064755a6de4ec6fac19e5f48004feb23adb55a0d0253890b0697e7372a542f7433dac213c7497f554f0976998eafe0bcf8ac03f196dc97b00d8c405f476bb8c648a229e75e218c6cc2c7c2c153157d34cb3fc3b07efeade07cb383dfd64d15f15e430e6775d047bddcd64bfa06c13818702aad9ed5329f8abfb7c0ef768c6ebcf92017cfb2e5cdb71a93750675c719879a2bbd9c03544a09d9038eac8422fac5dfee57b5d9e9883e2064d38dbb332a4c7ba3d3109c2b7696122595c9f3ec8b11b9312dea0eb366fe9caeaebee04b27052e457fe76c33dd117b0fe7fc868a808398bb05c0d6b56f2a12034f476c21a900407dc4c75d81aa4f93079b8f7b46e7d26e7d952f16b60b9fe9b6f38cf405234358e95742c1500ba3e7fd5623a6e128c5c1e9d20147ad0b517d9622ba2c982fb66bdce2ffbeb8ff63a4959aacfe636d157a00db80d95fc1705fd1ac573bb82b34ceb06f255e7defc6b7d66db0622c8bb12c5fcbdea6b96bbf692349725066b4a17259eefe360576e1cdaae41354d1cd7306d5ceee063b0c65eac3c293f2264d3f8205fa240d7f7e9808c4401db111767a06e17f6856096e9027ba1f91efb2fe2cd3ccbb1458bdf0fc8923da071598737efa80d09cfa14e85d70e660c2235c1ae88d2296cbe785a92f0f68da22668e0d50e8472e74e4baab611a1e087f6ca164395a7d1c9a53e4f883a2b5a89f6733001eb79ea4ba5e27e79dbb4194b3e900a9b0eaf7320eb8e452b448ff12870d0f473bf48577e952f0694cf4c88b20ae1766beb79d74d887ecdba47ef962aa5df1cd4985bef81d7a8828e082e655d4e83a3075f586f2f1aadf0d1e2f4b28d8b2bbf27727d780b3d9462d5e287254434b6f79c61e8b7270d103756145c25581ff0c639a9fd7507a57b4d7e48a4eb7747ba951ee940c53532d25d37052bcb40c19a4b1ef3f672615c42de1c8dbda89d2da798759508bc0215d52ccee44cf3611df7082913dd0388309d47f4436d99ae26fac4c5f32b05f9305219e2d1a5ed12fbc53b8f3644699df8e10f9879ecb0ce62dc4dd60185f7d1ca13508c00a3312ccecee8d272307e8df3f4e350a76aed1d601530dfa5287c17afc3f889cf6001f8fd1223823e390fc7a7a619ba5f408f2516d174b055c370cc7138fb68ccbbd2a81cb9aba526da1e935a5d89c568c9424a11762838ae9dd81d2822f395ddc2db64bd51358196f1460f893b436bd4dd223d22fd5c52a0716f42e2427f3e013590e712ebb24715fa9ab9ca9897c0c5b4d4d3ae4b41b258a31e1b98f8d3347b7f24df0bfd66b0498f1366ed361d453767658efe028fb0af10e130d64b0d2fe48271dc2298fc222d9b319b4c4ee554a7441bd1459bdab4a75f64a6adc206f28363d660bde0ba45b81771469403321274625e7d605808bbd968eb5ea07f69800294355212b109dbd264760972d7352eb85f3dfd997983a4ef0215396238f276bb71b291eef483467e24e1a05a9c6be40cd78d3faa6dce1b51f56b3ae08de9addd5bd156273853e1a09e245cefd5cd440c4e4a1f842257fca9dd842c22101e285df15a8c2dc1129eb49cb7ca77f9cd973d0f3fac94836ccbe4e1d13742b629028860858da9f85eab836dba7222b4c83ea9f91d098b472605c1de7721dc2c615853928ffecc1afa9973454edc2cc8e190d8b1dc56991b9fd2e3a0c64556af533ed2fba3b30701b821f6c293ad46c51fe10992764cc34b1a691382ab7a4285f0560cd02cd14caf5d931bd81a17f916f692dc325d2426bb932829417d69ec94afec9d2b537c393fb8d958337289adc58d47e3d0f1451d28d99ff5aab69f75cdfc989b153960afc1323c9ef758b6b412b4745754a3c953d75db49f3a4339cfb6cbdd86b9ab0e8ced448586c433cef2d9762c2d145cdec5277f465e586b528a8286907a525230336746a18de4195586b5255c4717cf38cf6336ae38100fbea1a00d25f15765f08e732421e688dcb30f606807970d208b289b613cf2da828d08eec306236a65c0c6b7070cb8c6fdbcbcae5515e5e63fb02845b5094a6b228231d2890f3a0ae157a136fe92fde1f8869fb69ecb74e2ec24746d8721ef81821e3b52c0e705a7ccaa5349a676a26b03e14f0461e1857c15c78bf884db840a176bcdd400c67947b09fb58e8d3d8f277cd58af7dc71a06c03bdd4f67d6006f24cdb871cb3ca5d12c407ebc7a7115409bbae845452ea2a7329c00d9b658db4a28174e965349bddb85978f5a78bf17581173e4a2ad0ddd8e64d13f6fcb91fc0e0fac263c3aac4e3d0c610fd50b2fda63ecbb142b4323406b37356392d7c8e91cfae966572ce83f196287783768fc724f73c4251b211239195964e9b153351e9086932256cad1250d17a5edba94ecd94d5e73d61cb7d5e83af29507fccaf6b5eb29936e6923377e5168eabb9e1c0fbbcd3b9faee95e78aa32e8d272d8f64fb1ff47e2ad6ea66667d7bd8474c1a5da0950cd0f3cf1e37e9d606a0539632e7e155fb45b1123c13367978ae8e2312dae075a5a4fb8967c81b79d2a14236bc323a82eb1bec8e40eb971960fdec81c8944975d73455c90e0e7f20a39204486ee6f474318276856aa36492d256f9abdffc1da148b35a27623db7358ca6f4a4b7a82c13d9b8d458deced20bec44b130e2039466c6a97524ea3bb54eaa3b6a0534f2221de993713be2d7de40cb333029d2334fdd65b280a8ee2299d633cd18baa20d152ff3a74806bb8838f2274090de22963db9f2349dd59aa1135870e0c920", - "priv": "a46cf4523e421c0d7d3a8cbad5240dfeccd41d6b9a1100a209c25df5bb226b80a036423a7c587f3691bb13ecbcf043e0f8bd7c855cfed99b2ba491b362914c849d8a842d707d695932927eb1fee697b26970bbac609bc63c05d6143f1a3b6c46268a3fcc7c50c50aed7094ebeaa53f187df433452a9d91e9be5243b07ce35e91dc022a21a27020c04d23b961234902844264da1466e3a02551144d934008c9867192460989382de3968402433118218142964c038330930206cc861011394299480498884009990d63068a42b82d09a74922179242c8709b006d14c2409888695338328a124a91367202b08182c821c202721ac6249aa88cdb906424c30091466dd3282c89c26589c43003153193260511b544c0400e51266603054c1c29809a04900c9521e1064a13004cc0008e22b61112278c14b62d54100a130046834891c81282020940a0282ea0a48021a52520a14494000513c528c824905028511cc2315186895130322026658222001b472a141744e2800081b64c9a864911837191864563c43024c79001815121292001b621990829c3284a8a86008900058a128d0c1008842684dc2852e1a2480223280b44658cc25113138ee32626d20071ccc8310a468a24b40522b35011092100144d8c166464b0901a25899b48404c944519874c20462499380c08936502126ee0247213b5448c441158c044e422600c03644940210387718bc665222521a4c67049246a63844888266a4042489b200161444081120ca18221a39428d3b2019b26840046621aa750210470214620e22605811466908044cc24841b334ccb38224c1610241229a0a22043320460167111174c52142aa2100d989271d3a08112014dd2b4041a82440b13459a302e48485150a48d14302152c40513474a6386891424900904828aa6685b446a04009111b485d1348a5a4452db186e18286a4886040049101c130941387000b810021472cb968d48122414404c9a466de2c05022c43181c80d4aa60d209741c24804d3c2711ac18da0304a2327920927298b18110b084181c060e1a62801216964060949385181328a6232255b8651e3b06444804d1a89695b382611208462900411850dd8800401244d62b06443448e41a22001806419c75118b86ce3461012278e189204a1a04002402108348a19158413206952a40d0a1000214532d3b064031231e4b430141481438471ccb24091266211944d08024810228e4ca610c3222d10498e133009c44482538040e0487284820c9cb028c924725ca24cd00805d302640135011b03111a35111a90405a2068a2982984329121996493388ec3c684c9a62c14b590da883001343152044159188298443219224dd9a084182788d192298906851cb58d52a6858c426a09218ac41024c0000d5c467280a21192b24509802d0a454591406840446d84326608900452b0709c046a11304a52346eca308a5b16901a974409124448460c008130033312c032629b28814300811c89311b4368023801e0982d018061d1c26199242898a40cdcb0101c1900d9a428e0868c51c0458c888d91a220921649940846509804110650244651813021a3a685120860c3142e01176aa4484810956c8a226a1ab16924062192086641b801482002014849e2240e08b8019c942192b04d604046e0280e19232188a211c2084e0c8710049588504405d1468519872500a7245a0649d4b231d48400d0409041368a8b82901a232d182560c230269bc071d142455bb04453386224c64ca310610aa04164447018945114280d43064c98328ddcc20950b86452426a23364458205148a04cc3086c0207291c41441bb331a20805241492208001ca042cdac6511427118b1250d4160c91862052a4048b02410a23900c930d8b928999208cd2026023000503012a1196658b068a23a970198100c4c62cd21661c4104ee0169109300e54a03000286a1cc901e4485258466022a76d11361243240ce134605c089284068ee1484663402cc1088409104a44946460146608a84c11a94d0a3044111625d0988d44404c1c073110036854040691c06481180a13a82de1488a0184889b04700ba805549044da124a14932513384d9cc048c9224a1b462841b0881a806dcab84d99300698b2448846660b01869202465b482149300420438c09b130948891d3028213a7094ac069620831f5948cbc6baa8a32cdea0f833428d1d43b2718ebccc1842b9049f9f902a712ea5cfd4f6f30865b892d8b8110107ced2359c0712a1bad50cc311153b589d7fb3cfa3e6778423eb06dbbfe88c3d05d3acace8384316a09e9ee84ea1f84d33b4b371679758200bb14a5197853f073b064c51b6bc8af13cf4b1bb82fec00dde1a3b8a8387d0e3648238bf9d0df3417942d72ff6db91cc442759a89db0f5ba5bf6d2f23538b8a3d5dd0ce271b60b924de0517235a10e9d20e80d600472820cba150a1bde7b68cd81fbf334edec4904be707194772646d14ddc1d4d88f48e914296a3d682743f03e473e0b68e0c4018106f21742bc48a0245dd322e39680972481dafc364f60e330590b02f9ffd05b2537d250047b77788fc0de89c4dae9abce2e813cb30dd60b50eaceb31f5dbba34d1ce50e3d09258954407313a4092ebf75d7b63f3bfc6ead191f6ccf504117e87a3c01a6996f31cb0c20b6780799877456f1368a08abe25da83cb061792f7896128fe181238a0e3829ff3142f58b3c6b4569cf298bf2b09210945b037d85e1be1c46967f9c0778e1e4e53e9a038958ddb36aec2f335d65411f6e39f70fdf20e9ecb21f2329e42e764bdf15c0acd37acad87d214c4aa95bc5a644961fd79b7809345488ab7717aa3e29f30af5ba4090d2547e991ef1ed73946251930bcdd84155f24dee38156b81bc61de7b7e560f1920fa0477d6eaf804675268146df90c82fdfb3466567356a7dd3b9f1bbf644dbdf68751dc5be43b0472043db29e180819a9f77b92a9061f5795bab14ca16ded452617e0ea5e36e72aed60bb89d9e970a63eb7c76a96c41a295cfa58d454ca9b6d5e113aafe34589d536d909cf020e407aea87fd5e0cb9680e7ee81488e48e4f64a3123ff867277d710ccd1536acbc4fed4a104816119778fce2150455392b76e60ee0bb6a1440da1232f43f2fed546b360ccaa0b6a8f9cebd01e9fa7b077ce88da11cfd8010c4e4acf669adaf7709362921121377d5ca59b90e8ec8404b1c24e615a6d4814eb31fd466882cb28296c8aba4112fa026998598e70d57c8e212fb7b6959d00ca2998199ca32a91f0c489d5880f7daa55e86554606d10237437b4b8345d90838f82a16e46e24a66ea74bd23db13c46e09dd58fb78d50d90ed9953066a0bcaa36cc0c0c85e2b27d18fd435dd9378c6e28d2f6f5dc3894370bce00080f8b651b464fa36776b221c631786ae4fb63b105404c7b26c186ba6330c405cdb603ab63875dee4583cd9645300c8120fae78c27ee2dc5af130aafb1e8ec17b4bd8b69d9ca25a477b355a4c60131f79f1336aaaf4a58972a74c8f35bd08004bbdc25b684630d28f6cbb55f550140df201bb52fc65977e5da77651a47d034a479626f6083eaa78bd1e4a3cb475ed1e82c99d51bacbde6fff8a68f8cadf34e86d9d75cb80026cf5a9eacade4740700ddeb5484b5f78b562b1cfdc2f9b6f58367158fad1adde6dda13a171e770d8994f142cf4212c9d936da9456bb6a2085580b71734f533d9a98a52d759bc33aca0ccb1f2a0ef4514d4b8a77ea044a269400b0a5d99dae4893bf8863936d0e86fb1158de05d2ca0fcf9e828307c280d668a2abb5252b0ca8854fa52079d97bc4ee74ed42041ade3fd3cd958d70a1e054d625de0c4e68736a0faf2316904616dc34d0f5d3398c92cbe26dfcc9fb3703bb86b7afe383e2d743a8ded9fa47ce017dacc3ed7a9a885c869a883304389f2635adaf7c7cba6333b48c6e0a15ed77081cfa93d60942def62054c352ef062068413766f15c9a2b41e77c009572865965bf3fd266078afcf0a75c578db1d6b8d8642900f189187166ac13f2bef26098133e2f4f08a2ad9ec7896849e0c163942f54dd52bea2f2a62a9d207d282aff4ab9fd52593db24b4416cf306a1da3cae074fc08d6f29680c998e46805175b26f3a8c006d24711b164677370cba9d3a913711ad7a22c2ac3a987ec2b15c8a7d512c0c44fa574c4cd85f8a9c49dbd069da0b2a1cdbb0b6c47a0b00d8da6a384fca6dc17d037fafee79e0f7d14a6b3aceea7e6c6ef760e9c9503b08316c6ae34e52767f7bbc4aae00623f165af74426afebef5d8f909c6c78c010266de8c27c492a58f5faf5adae8acaf83bbc40077631a17615be6445e63e8dacb544c0750a6c32166f342c580c93131c059e5a93de62917d84613f643087ba9593e989decf9ab86030ea153a19f98a4c437af1f21659b0d404c618dd8107914d09da556729c384d70a99707f63a78e57fed9fbcdb8ed4ac40b2be297e064d275aa2816c24f0eb19fcf8906471198570583994c7398ca58b882e6af03a9c0375391210d443d5887b354c18cfa4aa2b9cda6e1e468064a213d7dcd56ab93597564e027bb7dcdfe493bf61636f6ac814ab81fc54600468849ea04277361a9e9ea3197dcbb9d5c21e6e2f0bc26b248bd018d5ab617fd91c2094d172840bbe95c93838a783f846f4148a69ae199d32ee784df5d219a307b862a2051668fb38ef0d48ccf33787f2c5ad29ac37f7680c7d9db9139cdbeb4311948cc3fbc9d79510098ca96da68310ae05271f2d622b0942d43577d24942f0b844d21f08a73d61356281ba62b0ad11c4b2783348afef206e93e06d7866fbee647a1c86c514a265e5a8f2d86b83fdf42b02301dc3b4f3b4337c354096a769cd281d11ee2cdc591a99345f1798c03972db128d9a56a69095ef30052c16c8d4e55a55346fce417f5a8335502478da3ce23a215576116748d6b2c73f5fdeb95679341efe0a8a637b66f7f14593b08eabcb485e7c576a10fc3a67e2dcd47319d94e91033e5daea0d771e891838259698f866c436da847cc120cbf6512d2ae126226870e8b5f5a15f1479f492b1d25f47e7e5da3040426362a84d0273236a56c2102b1bb5cd81b1d5f14e675cfdc4ff0c9617e7e5782a672cde585c113b9e62bfcdbc2a0087d6e4bb3a674a742c661bf13c9ee7f1e10fef08e600e209112dd3713a001bc2af7b913f8e90e7825067ddacd41f7b010c12f6ac816ae03954f8881c28a0799fe71e9fbbac80b90e15fe5d2d2333f69f853a322d3a82140fa09b38d04d9dc050c5c1622ef9abe75135b7b1c9283f62f2e06129ea56e96fd4943d8ef9ac6af9c2780f3887448af99d9144af236f99c8602c68f9b87203e9364b21c257c68b8dd7d8c4504eaa29443256b10b8f98008b08761b3ea496fb13e8d939813d1d6d7ebf3b690e777dcd0d9a184a4a6c3c1f90a4f70dc6c367c5cbdfecedc0152fe679bffb9f58d983c6d6cbdf76ee19e5697a3536beba230442b071c1606e3fbead5f7c1134484ebca45a6c60dfbaeb396eab8a12fe0049e4d5fbbf64c7978a1c67452a0857fbbac0d7add8ff4e5a69f619a1b1386426deac4f0596eb15f26968630419ee42471aef7d21754dde95e65a0bff3a6ab2538657ba99e29f286d1fa6561e7d70b3237ee91675163759292fa84b17685ea160ec09fe012b0832d674228b55420587db8b5fc12260db292b28c22eef883ba07a8f70e00369483a0868873d65099e2c0ba97a2f8d389b6756665600a7f7b2c2789ba384ca20c62aa6056d22b4f85792911419ba4f5a07e0995501ca95aeb324e865b71faca8a9fd11f20b4e02dae16832b2d00c7292185964509076ca18c1a917a8d7eb5c9ca4b3776f04d5d43ea399bff3524ebc339fde732a27fd3574a08ce04f8c30a7e3dd693601a6be6704252ccb382a0043f6f5df2d47cb808a9f7415406a911251d74342c50be5878f170c795c1d9bcdf700ccb6b701f67f8961f9442d0b1af1ad32baa6274a77f0784e69891ab7d79b9d7c35fb6a345327efd8ad52f5b2f231115e32dcd020d5396fd74245c72edec18fe8e0c5991796aab1a06243238fbb72c4c734604bdf7446d3512c1aaf7a43e83a444af3f37215078e55949e2c22795c150f13b65f6e3d94f432e8a2ef6eef37018dcf7030ce8c4ea9fca63bb7fc7460d1e8c56f5e066c686fed51dfadbe8eb3e38acc64e1a01cdc8ad425baed1d620c8b87eb00c876e1014afbbe22fa8fb452fe032d0406e8f798c9a3d1a48e69accc18903740165c43473ff5fd69b9cde3d67285a9237035ac9a8e4c21fbece5bbbdd560e614f70a85b6e73f30808a60fdd39efb8ec1e084ffd9b0221a2418ea4ad9d7b808bba2fed6bf0fdc5ad5f157f340275a8310b8d07946601203e3812ed20bdb6021e3b42e92582c855937090fa7af08d5b9b47146c0da7957243e53e3581716e03e026fd94aab6a1dd5e3a9929db6713bbafa164e7b1b9b17196159279a6a3f2c57e9f5b8eb379ba18ff363ee251341fd16be1facad32e60aaaa5ce530103a7bb5b8dd13b8d09930a061ee7c0cd92a402381fdde53f3a780b1453c62168f7120c17e0c8e13cc131b050533007b7bceba02db6658d806802ba5cf7fc5afe5c67e80284b13bc2b0d6191179e6a6fac8273acab2bce1a9b085aaf08d4dfdb74d1257d579ba3ec357b1d2c87e28653c60ff63c511ec8a39b1300449611a66eb9c3554fffccba5be2a90debb6815741fc913199c280a90021cc800dd3f1c3249e442a4622e9766b47e858d5a1cfca3d81606661b491dd63c494666f03f8cd17bf5e9f88166e03b33fdec7b60af412853d863c96ac6e1a19828edd988bfc0a4065f1e0dbc312fc2e23125ca31c9a509e7abdaa5abada3584" - }, - { - "seed": "2861449045bc0221e30a8cd4482b160899956631657095ec70231cb1436932f9", - "pub": "967358e2cf1d4005ecde9d0165d7ec9b3f538094d51ebdd3a337c9f90cdd928eabe204c043903e278619c36dfbc6079627b6ffc3748f58bcc7c98aa4494d162bd4ff7964afae5ad0faf88ca07cec0b9f6cc2b2d56417e7170e9b2c46277ec0974c9e8288ec1c743d87a58b0940922b1312b4161b179211d0c124852b94138da602d87ec076d2299a390fe3b6a3f7bfed92d578fc785023084773c2a90a68d4edc449aeac9643e3dbe4bec8d2ff224ad31cfcc8d376b273bad4786d3fdafe10ebbc988acec2a850b9767dd2d0b69e4f72ebd20ba14c3cff79fb0440f33726d225e54d8cacf22531c73a575885c260ad371d7a2bba0a054ad71995c561a30fde9e808d1b8615e2cecb1e48ed2695df69e059bc3f676e642b70e1c007a2fed8ccc114291d26709ba71047ed476bc89d8295d3d1d2ff54166244bc8e2dd3ad6197b29b29f91b284bb65988a413d6e18a59a88b85ad97a47b891e5450aad0d45af086a91c94984695795d63c317f6be3c9b33d1b1e39456ac59ae76bd95e03bbe61d9ca1ab03680999791cf2377e703ebaca37e55386fcf34cafda79d486d2c1ca4350dc4c097229c27681eadd855cad89d13382ca55d6063d054f2bae8e01a7795eefec2753c066d15dc5d2af91d31b61f15cddadaa2414d85961a37395bafecea1123cc672a61c2d59be5190987e6f1d9c92aeacff3a8edddf5b2e62b89a4690ef8a1a10e6f360f5b477c8f893115be636fca8ef983be2c283764f735e9d2bf3288ad0240c625ca0b3621f3440b9a2ad744c70a8447e3cc70694b05e7813ca3b5d994474bb46da745fa8d599311d02d68cfb1f2a575e1b28dfcd75e4507899d06dc3fd39b15a8074566aa5de757dcf43ca56f28e66fc79dc744c23aba270e7ee32fecfb99d89454fd48745c4c9db07711bf391d54e7b43e8dd951f28304a07e1760d0693dc67c1abb34011d27db6dee197ba57369679fa722a754754790c963c3180963640b4c643aca43c93c75f70dac54d2d152370c329f63944d85bd1c515d07926f133f03c141d19477008d1f74e1101d1472043fa32336b00b8f65e35e2a8469e2bec32a507d9972d2831ab47f7f7e9ff62716b7b83a9dc48cb24ac46806c7a5dca2f5ebe1219902f7dde0e122449d0f98c670004982d8ef4dec48ce19394e795eee9bbf5cab44a408d3ece8c11ee9e979d6f47543e1ec901b520367e77db5969c88d2477d75a501c54d177fc9be40162f6073753f03f12716964c446962ef8bb924aedffe90f2d0486ac9b7d92be551b74153d87ec9d794e87fa2ac0089104a973a0215a1088b4b23ef5049deb6db221cf636d270ef511ef84b90b91ec2ad815465a6af4f31ac651d40c25a45b93797e371c00fd2c0b6cdd2bba34988f3ac2db2523d227f707613e4f181ea5a4faf267eec86de09cf6c6ab2cbe34585236e540798b1a1ca80bf7a50e84101e96bc3b66322f4ea0253c3ba3fecb94f96ec0b4619bceeb17b881fe4657c85a3716d2a5e3088d2a1e9e8ed82f1ceae3cba04c70051c4f64b6953042606e9d22e601771dab3c44de172c7c87bb030e37cc00c334b534a10c4f5a93c8e1cd092cd205cd13d8860d3d22bc2d2ef7468d50fc9c4c910c10c7416494d6c3b94fba898389dcb8a1232a9ab9d2c350438ad90b52bc6d679eed25f5e139a7f7e9bf7464b9c4e01c4d634c4bfa40b0cbe2e5c0738450139490baeb2135e9a97b2264bd20026765be89f0c886fdfb37295978be462d865143a9abab1ac832759e6b450ed314e41aa5dbf18febef31c4fb86a547a3551f6715b04d6ba66180b19ae6904e036422be6062ebd9bf21f638690547a36e8dcbad6c243f62dad62d4242c08332e0151de491a18e026aaa35f7dd296119d45346c5a2a657d9c6a7941d52c4e94fde8e95866bc0d932f069a3ae26c1589e84b5238dc9c96cda3375258505156fa19b3a1aaeb268e818862f377301e172ed8e72a92c6f0680a6a7ad1fa5a1f64b436e6921c3a82e0ee97842221f5c70d3292511e06d228e9d3dbaeee8306061b973d9e9ceadbb659a8c1bee6c84b0877ec5d890a4b723c9fd1c172fedbde6a32f6d006cc9e809e946716588ff6e1ed60f7633d16e9226f60288a9a37713d2a93e56d3173196eee4222b992dfe9f5351a2441cd7e43c4fbd36752e6f5d0e633aade9aa2bd6cee0779f1b8b995c783e9e011e7e2a8c41c042da3c88d601e3800a5ee470de9da91e8e675d21239ddfd9b41165c72b116fdaa6a02315289760343a4dda1700412dcada8b0145751fd8523fa2760f015d9eeda68b19d2291aea46a85055f96a84170bc195df93c7c73faa47857aa24bf703d65d40bf40afa6bcea5ae730d185d663b5837ae3a4629e2724d3bf08b649e2e4f28d05d2144c5db500d0b274171226fa680fe9121cbe27577ea40dfa5b1a9746795d988c83edbe6a6760e28bc5e23e07da89ad1a0db9778675581e64b7104af96a916b763547d8927cece1561590142b49cf25ef14754829288267707d0de1595316ab21e7ab94d369379b73724327d2c109904659f9893426d944ca880cd2edc5a82d95db7ecd769a3365fcb655f4730b42828b5a1e25906d66ad406c4f0e4e44d4ae4f46daf382497b4a2619d1ba82d07de5610dbcf7d746ceee7192626e4e64221aa393cff4c960063cf4041c3539319baf1ad058112aed6112926b45ebf28ded3ecb57607c09b5a2b0f25b4a875d3a0f19f6fc2f95a8a88daed6697bac3983aa7b472d68243457e453f5f819414c1bc5685fe191e74374aa379a8c079bac58b07522f1593b4360332da0d3788ea6e21dd72c6a349c4fd10c7c360fd4ee5744dd24529a60d275a5be05e2d7e6acd7335a7d985e28f8c6e9cb1b5513f3e6cdebac655fb6aab00335e056d9be99a8f6ee5bde8cb1c7594e0ae8931e8fbcf3cce4893216c4456e85980fba65bf8f6d851b4ed2d2084067d2b956ff20dec0f64fb28f80d9fd2fc9a2e613da949368eb1f146cc5fe8b2391c13a2b225d065d98b7d1f1515284130b863d7ba42ea4eb8143d5c8b4f9ecbdb68a75c1a976d3fd16a153f612bd15696b5108a6cb876e7d55bc1fb6e7dca632c9712f3e24e13de674aaa706394f1d19f501dae5e57b4d40a5f01ee5397ccc59901d63d1db83e6fa2ad4b7ea39ef6ef56d0ed07e4534f00df7b67b992fb35ba9746da60ad9064e3491002640f7f2782c1e744d94c2fedd26f569c2cbeb44ce785a2659f2de6832d63da3d04f3af0ac21e54c8f345aae23bc52884913bcd64912ee98309feca4434d5366b2af834d5c8a674746a0483b27fa94e9be35fa571c4be77931ad2513287ad5e6ff40c9091d5644b87b7e83e7e8c3fd6e3c2ca6990722bc28f057823fabc3704bce79b4c74d7f670821172802f7df5295a1166142b54ca6987428d9bd030927e4406b31dd4ebaa777414cdd69b25a8768b0e50d03075365d30430159ba60b16624f9bc115752dec3ef8d1b3b7c8b28b14b49b27ae9105afe3d548dd3d79e51b49440aaa4d22a35c3c99921a7ab935326c5591b6e6d8fc6e7f55e130dd4e5dc4f6612079f2c9cb35ab750c561b86f8467c9f992281fabc27182e585c6214459e0341f7ccd805f76e29f9051765e5cc9e1bf30699c477eb0f3d66b4b962cd9ff8e44", - "priv": "967358e2cf1d4005ecde9d0165d7ec9b3f538094d51ebdd3a337c9f90cdd928eaf637255dfefcef5f1f512a3dbe32b86c276617b575c9960e38b552531b3364d166528cc5be04aee12fddd38a4f9491f7928b76f8fdce17566cd692e7e417e63a8aac99de9301b93a4a8596cb6d22528edd434bfda907961c37fc175a9026d3f842828db962de14626e28604513846234081cc989014282e60240124976c63088a8b98040c024113c54da0000e5c4826c1b664c8a0885c4064a2208a91a86cd4208a53a849893029d3184e5b48441c482a4a168492c26d018350d2040542162d1a2491848884dcb62448024c04b08810447214190c59426653108c518680129020212766c88485099560a4c8300832256012801485880282414b488ea348009242050a03801a3220c8940801857191242ad1a260d3024a98c8514a346c5a2041cc4484629044e2460cd1c64d0880845bc8040ca065083608a4264da236292003818318484c420e9818425cc6600990910b382519a664081124db4668c1289289166123264912249284246a88a468029050d8186ad8420899a08102122201198011c42923c849d30031884890e1c420e2188d58b6692230528442505a280c5aa271c8224642860124474909112e01862d9b002ad9183219a36ce0286284840519444921394c0a308204273089b66d42282ed9224219962c13c224d3b24d81020e241509a01421db06481c366e52262512980c62141198166593b80990b820d32030c1a22042a46898280cc3c42d203821e21248c206850095711cb5610a9464e3c46099986dca444000c42050162a14016c08276424b08d231251191240223785229469c3b84c1a3200129131cbc085a408861b9810a1b409c89409a4482a62904892a60d883830d246320cc584120191e3c22dd99288d3b820094642d89068094426e01009dbb41040106e214404620429049731d8b8304c008c22170a20b14812060d8aa020c82261c4c02188184281224e8a466de2480a1b80450a956c0027510b856410425002064204170d0a102a1ca18d50182841868c8ab44c80142142a42111a350e3b47081366852284810046d183424c0124dd320454bb024db128c8822655b0609008084d8408941240e81a205a3280e9c16615a944cd43689c3208a19816920a0681c106804c1015a100080829142a20c21148943224c1a026e62303261a441d4300c0117081ba764104785c8308240882520314da24448dc4200d2082d4a2028a2124ec196311c086d0821064004450aa41084062609454d13240688329040348e0a076243405092946952141014498ec41826d4326953a04800a75183848d10310188006414c840d4342410b809c2008511284c1bc248c0185223b24d9b2284a1369281926da142406244469a32201b2784e4a864d22606490452598841a0b8240246228c068d1a982d80123153108e192671ca320598a421e3b08c913804214752033131542060e3140219199243486053186258008940144ac2346482b6901b12251319084c864de4320e4ab46063420e134090c12242429668c0101190c64ddc82300c1984099270e14861d4020de1c668c20472d1c605e4486813b53014414a990041a114621a204e44c42c53482601a96524b32c9b9449111201934070e3266a998070a0262c50a2508b240c91262594068223314813b090441660c34200a322901c274a244092c91044c43670ca466163a800d3449081a8654920808c464124b268da408c11389242b24188228a61c209dbc62409080543864124c76988945050228200339113404891280ed0b6401a2721113191cb3052232992924662c0447290c2009908409ba07021870c0a80481c366484986922b14c634031a4267058024cc9308202a00511c21161866588128800968441984822134c1035048ba8005c448288b00840a230e1940d881632234585e3b229cc946c01464d43384c019310da968d98486edcc8254a804c918464a4025114a5888ba24159866421c461e0a069c3b80cd9862c9b0622e0a27182a451a1a221892068cbc6459924521cb948a1340c11410481448e82c0415cc809e18621042252400225218189d4a44c1a44004cb46908a0849a2632a3b0115002288c2288628444e1b049a2446ad212824818081902904318860a896820b98818960589060a5b862801ffba4b9f5fffdb23dae33ae1b69fc1299f5b0874f4349fee446885e9c727ecebfbe6b6ed44f58b6863c671577c7273f7eb239b1a4af286ffaf160349b30fefa86a6d266b5e51d5448196deebcd27df35b17510d8dca94bdf571de2494b3934023a424f0aaa0c9737af48b08da7730082089cd711979b350420c26fc7365d18a6d48eaf790cf6a6389691befb9f502ed394a2b99330db187fd9222159aa7c65edf8d47063378a28e33a6cab7812efc31338ef647abd3bfe233e0322715f1796ca156191898df447da248519943669c461b4bd1ffaa7d4b736fdcd1125197acbb1bb5661006b5d7ea1f2a78ad8fd8594bcbe43ce565cd8adb3518f8db36bb54574b9041bdc0ce09fb6a47170a6fb719ac0475eba5f3efd955715a0025158c26d1105bd3c1a60bb75a32d220bccbd33e13f84628bdc5229a6da9078f8e6a0a0b297106c8356137fd9311f59d422421a932ba33f299c1a5883f053e954ec8f4a8e9c81ff179d9ce2da58b9709b684f321ac496662821523a8b3eafe596203ea6c0fe08bd31f8801dc9b967fb072787fc7ef74df198131261c03ad6f85ceebbf4b2b6ccefe47180e37b05270d46c5b78b263a86a8ccebb188f2b343665b5c3875f742314770800d55627f81fcff1f931027ecde33acf7d6e56848daeb6c283d0055a9f517a31d90fec466270148d4b81f1b930410cfb297cb632562153392c7bb0b6bb0e95d9015387fd6aebe67c801a78944438376e8fa37d7a919e41446556e91c6b78ac610c642fd6d97bb65f3b5673a38b463825e225e7a28a1c8f6f43cfa16016ce666f7bbaa4cdf9573a429dbc6bbd38d6ae9c8f49687e49afba67a84c10c9d05dcf0c7949c4f929cda3b8d8607cac53a02b88ae49167567f015f2cc6efaa0527c8eed7f9b2efb1c61a6c7429aa95b5cbb79472298567afe96d8b3d6163e794657219e4e0c1eefb6170f9703be95598f4b51f4caca38df594738bf64bceeeedd1056ccf3e08440a8ee580e4421b00ce0481c6b05de363647672d38226151ce149d88db9a98139e5da90490203bc712f64c5c4a36c6eb6ff1197dea18ca686fa3b629d04248d7400df44ab9dc6bc76f732978fb0c70c2eb2e432f807634d566debd3a2c24b076ac38be2094c59ace3428d11f5cf85f37feea2d865b1e4dacbb20fc62740fd53b54bbc4a2807c178555bca355c141d82dd79b7d68200771d386a51ee78dfdc7e1c50b3d5ca5392e5e32f67dca55d6a5edfe1d3b71bdf625d3389c6bf48a14f524e1ea21790735389e891b8dc7ae86a2919a75619615895517d243af03dfe8b240a7592c4e6427b1924430c47a672dd21ddb6e37a2e95ccbc533490137d2e5e62a08fb1ef20f402a9e94e133853755d2b187b798acd054741b7fcb59db92ff3b211d3686d86d037ee0ffb19a86c50913341c75464acf7f938439e9785a2e44cc58eaf1dc83eb5b83d1d6b3006450f2a5af9d8d14cd3ec71f6dc57015dda5bb19a0a027ac3a2b19ed912ee7eefee8bc73b5892fb425997cd8c870f9df1f9a477f80350fbb9d6065834ad860fb689a3396a232302ff16786e4c9e615e01f2b57151a9043b6cef8e129d95c5df3401b5b1d3f1bab04073bba65a3e26a708f575bd6997fd885194f81d2e2c4aacd44b4439a329dc5ee3e7f2966366f6fb161bb3b434798ca20a14ad2363d756c8225331e65d02b5328430dddea8b10c96e0c4af20668f19a611a12337e48821e1b49968fe0a3405e854f754cf15dfdebaf62c5a3ff77633171b9cebdf6f15dc592f006c052a032beb1a1df6f9bb863f11d81ead891ccc33f605dafc1cd3b7676436ed25d79b441520de417f21c6b68a180998d04017f13e66dda801b503c4682c68ace668b9b74f86d0709e13f6afc22bd1b3d7f0dd4baec2531c5cbcc8ce8efa4438d73c8007806f7c902f29fb357ee11c9bc7dae14121c44ad70030bbedd899bd779969866d63abb8e1b8f4963e5755fceb74f5ccf1d16cb397e363665eb15d9918033d17e2213f032ae6c2987e28027663f6b0fe293be52bc2dcc2101f61c61a5e2723703e9f882a120e3a8420fc94afc98c1a6507743da36b46e727dd813c1bfa63563065d03d08c3675720a00180a9c8cb46fd2d3c40495bed34504e97e0ba22cfd8e5bb87fcb7d9f4ae6e198a44819f06fa0aa0562dd5e5285c38498f9f9a37be3db3154f43246e616ae8be79bdf781b0297b90104e7b20a0889d4eb4c6ae982075cdb7d5e950877aba39b452b74c89bfa6801b52164222885cb351b67f7ee78fac0b76d8c88590b0113d505a0aec903d306045ddfd78df74a9cfa88dc0343dfd4d5e119c5e118ecc1d1a4a2bf9fd2917e388828d8577b5c459f4826697d1f368e89277534cc0dc8a668164f633a1c2109e07b4f754f7ddb55ecba31fbe73bee1937f954c67dc43ba2486490147fd1213551c861930ebe5430420075e0eb543ffbc84b270caf3115efd8c6e093f438c9b333ffaa020ad92c5c7b16f894928485de108c9debbe939524ebd3cf7bf2c925fbb409fa66c2e02ee70861c799af69f260e4196ee3105a7219cb11ab06d44b2a0264a5d753c4fdb0156784ba0fccfec197733eb9736460cfaf1e987ab3e1c80737162ce540568aa6f257fdb64936455fe458b4a469263aff1b3433290fe33aa8bcdcbb3c6e6d246b1a1710b801b7cc5db9a53d6cb7274841ebea1a0c802063c0b7d5331e62ccfd3e14c30df81a7daad8ab962387fabc578927380c0770e90d875566c622e916be2e0ce5d7bd1817292ac7c8e4942f8b8e755efefad1820aa2abaeaa9a658f72ec0d20a492f956363285c29567850a469b6263cf8fb9a5666dbd73ad72d914d1b41e7ed25e327c3b542796f49704c4a1f69bf53b8c202f088add7f7ff6d704208ac4dc49dd9efe2023ef4b579a7d5114c9aaa6b5f62b902b3ee2a375d88309b06fed057ce0d3039b638579c6a3e94a42bdb1d44ea71c2142d377d646636f352e3a4479c26137e0b193cf759d9127f635fde5cf3e0457e3c15fcc1a8b2b633f382faf4c45e597416e6651c55ed5428410da2c91623f377ca9bffda3cc90f2292b789dc10f793f0de05446ec19645bba6d564e241355f37b0a94cf61dd210db61ed9fde5cf05b1f4aa421da6a55bd426671b79fa989005a2d2564a90a0b335d4f9d7890d9ea5a689cc2b577636a682949641c7a38b12c394871d9e067d1d1a42ae12c26f648dc312a2c2d2073261e38a0cc4afc136d448a13a145fff0b212e53828a4b938ef46bd2179f0ff0e0322643d1c54541b46687781fbd21411e838878330a1a9d7c1e2c1ef81a7d1fd84efbe5fdfa723639b787d2e5e8e3f8e42c3fc2bffdd3e7e84331df99ebb0da4dc2b939044e93ae1b8b4a46cf57712e504747fa4fac63fc309e673ff06a537c3d355508b6262b4d34de668271735885587e24846e4f1cdf4b461cb057249c78dd9f223eec1bc3dc07ad6be74974d2ed9c0732b929ccfe3c20113abdb941a857d70e1ac16fd71283bac8c2eeadd84ee7c0814bee8b212cf036dd9130a2e05d6158539d46835cd80e8774090d09e752fdd3a90ec77768e8e05a66bf0f01a56bec87ba51339fdb82baf40a1323c5ad23977858c8143c8c302b9630dabfd2c088e20459f8133386dce0583e64d3af5518dceaa4b331bb6f99a8876c26a9eb19e8e94078995a1f4552b884cf61f2e0be404f3011002886c31c1da179b795807fddd97257c4c6e178adc062aa1a9e83ddcb1071b4f4977dc80505b10d2f8f239c98eabd2b9e9800bf00f455f2ce3335e233a7745cd787c7b7d0ad60b4ff965e0c67b5644970954462b6dd9d21b83783a681634732c80de3ff9323d190290048d2f655540dbc8f9e8fc7640bf2ec43be78a7ac6cd5c28c11fff1f899646fc9801be7f8fdd1d682539dff53a0a37f263f1358d8cb08da73edd8d35c76bd540b93c81dc6d5ca6930f7943c02ed016bba0f66b84f7c3de42cf09fd917d9e24d80876d4c788031215b03e7e9121300f71dd635687f2d0c0c10383cefe13282b96621710ac9fb34eb3644e3cad700905f002e77e604ea5f615cdd21db859fef51257920d1c222f25d2434574a3b0539df2dcf3a605f02b578dfb0bc398a426dfea470621cac55a44dbdfdc39afdb38ae4baaaa90f046c2a29d40e7d222cb8b2f132601b564456cdc1beaf32ef045a3e2524dcdb5ea83b92510193ec8714f2c6eb3f109d1f96b56c39905b2425e93e192c9740ccea2d50ca7df6d1d021a393e10abf5edd44e453791ded69c652e885e526c8ecaa213bb6681e6579a1b7dbf8c02ae15f991f2d06157048edc804dca7dc4a1262a6eafc08ba06f08aed8ee48ef10eed456185b8d4c1bc7335348347fd001717c905508cf01418a438d0ec44f64f10999c06ec7ce736848b6ac56a7d5f34300b2b858ad227885cd2858fff1f0ba8e2ebe3ad06aa989e11b546e1d635b53d4cae0c7a60cf3f2399a14ae13e534f6c10d3166703e2cf1546a906f0eeced96c13ef389b98df19caa98948abec88e7a622cbecf9f9906fa42d3cb5c36e20e23131c3afbd082b4841394ae4435477e39ba19954889d7eaca6c41f20f531ab57516dc6c72229f1a5fba81f53bb848a511c8b3e783eac52de5be87493c9fe0f816426633be06c772abc1d5e9801fb6cd9d49354e004f99b9c96f7104fbff0f6ce428" - }, - { - "seed": "35e5cc06db4f34bb3e0911d1bd87432499abf8a3b71ec6ab357e478a2f84326b", - "pub": "f4cd2568830354052f146bc9bd5071e9038ad4e350eee84a1ce8b25fbb2a2f9688666a364a2d2d88caf9b51072b1d860e24f722097e9b8a336a2e5f40008f3bcde2ff01be2f0ca8c3536c99485114008aed5ba967cb2a3176111ab5f99331ef82a8f5970ef66d4d2a893961f8c8273f45a6bc7892606ef27b5e714984ee4c8e04181109ecd03ca1d52cbfbfd4c0c8cdd4dfe1edd2b12e37161409435e5f728dbcc9cbd7abf971b9983122525a474e87821a5b63a677d0b4f0d7e49db6977c9ad88d77718770f74adee2cbcdc5ddef47eb67bc27ffadd6f9f14f47584ac9b1fe80113efcaa7fe22c9076a8e2bc4d63dbb4cc19a9f57279b5f3e860d631feda7017a3f2311b92e9ee062cf7e72ed4136a7fba455dcdc3a5ee0dd8d3b952dbcd81db91a3a8a194c139f74a8b06274bed24d1ef432044c42e176de86c053811b8818329d8e1dc2d4f000e327626a7d8df0809a8cd564fb88de5ec4603a32a537401f9aa4a387ee50454057e37779b840160ad9ef2341fb56fa464397279ba84b818991886dedf683a83cf77ec9eb46640fa10d7540bd8ebf24514db0ded2733cec4ae4baeed9ccc685bcff1ddb0b4d93d99ea2a59d64b267612794bfaf6098f3ac28a1a16b4d635f62a202ebbfd4a4176cd8fff2ada0a06ccf8df09da6048b848d41b72dc44fbcd846afc15d8bd2001a0bb951cfae00415cc2fbb6a0cf8814f1bbeeed0bcc3c5ff6f3bfdeb0ff92b7ea1f4611747ddde2ffbc85a3df4c0fe69bf08d8a837017750705a1aaf0b8da6037e41ea9c037b4090815b236a2d5aa466b82d7fede158a5e3d3fba8cdd0c694faca660c959ac65aae2762c5cf0da790773197f1593ba89583a485d28599ac41e23b02051ab8ebf37bc6ce6055a2b33105eafe2609763885d477d76cf286d4ed1a2046bfb4a1bbeb780c2780cd6734fa5c5151af998a2092e68800854a65c6a462502e2623426dd7151e8339c1f2e3217eace536f49afdd2be324eeed0c6a8975a80270c4c46bbbc4a168a4c26838def3fdfb0d504248acdcb597f13b3b510ef034461d8f84d65df60ff9fbfe08f55326ab6e5105dfb16e6a0d4c129da2f2d37c06e34c99d3b7faf2d9b703f8df7fe4f4c3601ad2b392542a5c6241fc414e316bd1bb8250c0a08a3124bd6dc070364b1cfdf586312c9744530f8cd8b821bd2e7df8229bfc2fff10a628defe8965570c6e62daadbec432754da7367b21a111fe639869d95ceef65b4d60c1a1e45ed52d991fd17403608cc51eea4ac57cc200b3819876f0ad6e1bbca637e0058a7f228579dfa32fb2a137546035a3b5d8620b1d18db77c20a4da73ab4c83bdda0c9dd7291bf9c52d0891f5045d21efa2ea59cde692fc75ac3ce080469029ae9ad939520c61eba3e7cb839b378f77b436c943caee623adeabe91c3036fe04f2c455b5d7ad71a86759383c9abfe1d7872cf3909ebe4dc5b2c08d320b8d9155131c7002d57b080166df33a43fd59ec3a78ba36a57606e0b929ac1fcc4ed4bb081cb15647d07ae8dcd0e4f42bc8e92329a1a832ae1fd68fddd44b81bde44d4e763505e8e529b4d23dd62726a9b73ed3a5d616eb46b0f869561dcc52af438d6f88aba5e712794c959c81bc7951996630fa78d7f8e17a21a1c933bd3b3e58d01dd97ed86165e0494cbc126a8932930acda60fd371abb0121eab497d931fca9c7d42938001517d396f4593d56a5d5e36e012f9252aeba9ed8d777371910853584e7d60e00c6377cb5c2125cbb85a76a5a1d81f0528a813cc80735af17f1f85c9bb89ccfaec05237aee251aca22128a74e45760f3c460d2a1931724b0f0a3d6206f3d217c3c2de074f1202b3026afcc1c2d08bf7f2067918383eb6174ae7d29ccb086772f5d05412f9a401316393e5043d2e78ee07a31762bfaf118a99d20eb9bc9b221fbf4c7b3c3c74a2442ec4c5080acde1f4bbb8d237ac16448318ef2f5b89ede949cd086e6d146f512c5b18452f1c9e91daf255ea88a8fdcdc003dc9aaf53e0be6be580e7dd5846bb2b10a0ae051b0ae302545ba7e5b10766f0a472ebd130143b1ab91163204e4448c10cf4271fa6eda09532619c2e66df55f8f1e6015f11b322165faaed5f297848bddc1de2d9e972a3a20ffd56f48046ca94ed5587ece6f30a4da63e1f6c99bfeb594e22c39db0fbc3fc360c371b538d3e6cb53f8b7ad17b461d039ff2e98a99e4f17cc5e40cd8e05fb6c5f0268fa6d6e59fe4fe4e5b554c33788189ec5819a34d31352b2f0a08637cbeb59db8b9e96c11e0b28dec274ecda46b6d9b1ec836f589ac798d2bda9084557b88350b0ef9291ac4723f60b189893b87cc269d896d3f684c80d01cd7670686fbb686e86c3ddc3793a40d752c4eedd7499af3336e1940751c284fae70036dd3b71bf0ec3d8459b91a271c4b7e48ce60a245b476fa97d969d01d7a595844d4bb4b5f322a878e095ab29d616420d12d63e3f5a153a0b1dc87114a194ce225276b0182ab8a3e0b8b610de60f74cf358c419249be29efc0d6aae6a1a2947329291dcceb17b92d9dbd03996bfe14dc9f1b86b66ed58da10456ac7d056f81c5b4dc9ce09f54c7721f5d0091c0e4c2ba2a6432770a88fbe2c6d94e14e003338d4a2deb3de58f5dae1bf076145ff9a21d47bc6d1f82ae40ed8015451f13867962783df9836060ace0a54196469ea47949f0b7c18de9a5b82d733fdb2b82901190abe5216574cb563ddafbc827f14ca82a65d22b51fafc967fdbb4649943bae38485c31e5aceca6176c9f450af54cf0534cb53ed1f8d3300c844e4365264ad58cb782c8cea42fe30e25e04a4002a2cb02ca78a8391150607359a1d4625294e053184d77373fa83904de73855e4e861ef82c590a503d4305b1b1150ba5a15efd51634928851c0d6bff416454185ef741b7d9e463f8de7a1500202160d550cafcfedde91203a3a00901e511352c2dfe8db130bd2961cc9a163b93d2947a48e6b41c63d44b1bde82f023f73332fd8e4bf1a23cd143ee388d13d2c19a4f62d397b6a18981be15b2fab9498d1378b6cd420a939d6146ab3587444e30c20ad30c976e3e692b690e0cbd8f65114fc31fbbdd4be1ba4eafcd43c1fe3209c38781362a0e809eae1d640b4bbbefbf2338915c5becdb529dfafb4f3036e8e6b93c79e9c8a0e483f6004b94d45787ac87bf092ac9f78c6c3aa3b1c120ad5f42cef959f684212b1eae19b157b56de1315919fb5baa885039ce2492be3495d5b2a2898c160aa4ba35611977db873de62f1966e1ee4526850f343060809a9b143feeea17c095684cee941cfe192f342ced2e341d9c19b1f453007ceb701eba2177fe04aa95a78fb5513ef44ccec3cbce9d89392de571d94262c119e166f424fed62e15ef693bbfb784b58222fac49b9cda2ee07ffd5d64d8ef0c35537f38de01c4da64142544de7667f94295fa7c5b9c9ab79473a554c115dbd69dc5a58417748cbede59ed1befcf7c4c2f81983fed3e413df7e8824dedd1435eaae63d4c4b83b866d82d9bde33e3857d74cf6a7d0de26e3aec51346c3c0269802e6a0e93f0bccd81194c6a62a52a667c63c6dc6c7aaec750b1309db942a94c97329c73f7f2a01c47111fafb164d6f2d92f3a8ba2615e4012f040f962fec7ea63e4711611457003b80e87", - "priv": "f4cd2568830354052f146bc9bd5071e9038ad4e350eee84a1ce8b25fbb2a2f96657fb1219e3fe85daf179f79725671ed7aa4094aee1f73b8fb25d1033c1802877c7f01116d8223bc48de01d6a5ef441980fe5c969136da479a6588478736e8351e3851ca27ea0ae69059059511fbf046066cffd4c256037acc846945a31ec04300033241342a20891063362e81842511a460e4c8011a3449122292a4b82c2042820c380108166a0803401b883103034948a22d51448da4366aa4047212405142086c01130dd38425da182654022203402409a12cd08864cb402823486a0244651b2211cbb0805b16410b1026d3444c23366142403058240c0a388064c8044394411c9608c3b86400356404858ce1268612b624e294289bb6451cb3514086684b142e0b996c24a35082220e64c42d23119004812c9c342e50164620492d4a800982468e5022049110911b31654ac01018152dc2128aa3484852066219b60cc8c6841c010210c091d2168e20822d18a6044a966561b04c20876d8b2411211046043786c0026994342a44b60958b01040c200d082449b2830422064149960a346281a27100c200288b60140c27014246483122e20c148d0488910c824e294442432110241125aa64c63a62d6110311a2548a32012120661c4044612b70162989148362493242e54108258c23083b84dc34070db080180c64023c08d611465d8284912182ec01082609465d9140e112282e0168ecb886509302c12a17011c1259b328c9a842563806084402e52c801c04880580831122872dc362049240aa184010147728bc28d9c282c13172dcc2202a2961091c08ce444668cb68103076059b44040028d23c92463960d44184aa29030c14431918030e4829000c924081029c30290a0a46449340dd8160641040c23306ddb000c92304020085241a24d232744d180081a930d493689213581e2b085c39601d91452d816402118325334408222868c101222048e13295208b410c3c28ce3144062048cc1248ae0340c099669099731404850020046910212e1421094a831c4a668140680498628c986410c8310d8466189a281e3442cca88050bb4449302695a3681e40800d1a421482648521226c0a46121a94958168e2005720c242448c48c93a88c49188814136c11c381d8824540c84d01147042c28962362809250cd304240c46708826000a152123922988a47088b66909a42c220132020342234549093386500061a036061039859cb82964c6844a805160988c1ca288998850c2920d4c02469bb231c2284110820991148964086e2418468b06624ab86040a2290aa37123976491062111306d180604234160cc0028408061c9465152a84d510010582229d1c62d13132e0884084c469258962c240828e2b6211b438040027161140e102760818465d3b6115c388d0c8351cc848924138098068e59148d4ac6299a920884a2059a008e4c42121ca02c18494511436258864dc32630600406581642e2c2850a91811c2932c8187144b46091086164804d02276e1a262c2408292449081ba248031865a33646584649c8488563c661d8a04da346421b404c48b82c4b224204190818050409a420a2200e63a24002b860a1106c1c008c204652caa24d01a4299932204048716200201b344a011670e1a489dc3624c2a62512a52882c28c03954ca1b861da0490d2422c60b02449868c09468259362e0b23614ba081200264413852dc9408a3206518990400214e1c492118316e80b65022b36dd24049032382619060611411d31624c024810aa825e28840e03272e0c66050b00058061224846d84227108446114c868d0c670d3428ea3260a22074a1bc009088830913000db948d48462650b270181645d0a62060a49090a88009422d11b36c61260a992864980209c9c88812076260242480c440da022a4b004c11438810807118064862464e5a0448190686a44408914024ca90290887450c820049b88502072ee0c06d21b309048884c4a42c54a03051184ce104662325224c326adb386419a2800b898da3a24123228908167000162a411208c9187141246c12374914378022316eda488d5c380c24256e4b284e8a460c20a83019c24d21a584d2184d0b12311c13521083684bb04c4122119ab0010409121a322481244d12c49099c828e0382a221866010984c0c449a1186de3084e7007a9cfd63c9168df4370a8e9c38d996bd007b4d01154af208fa8a7439801393506ff280403a6e1df21fcefa4b76b421e535036e43e854a19074a643be822c8a0a52dc8210bd5c2b326dec25fc54d2177dbbd3d6127ddb56a20bda674eb3c408510d341318784b4ebb7213d10503c16e186287154feafc7aabb7402dff0072d04e1ef0ab5faa1cd112328cd1bfd6ca49a593e5b5e4a1128cbd5a3e2ffe309444931cfbf89b290b2d0e42074c0d1607440e1db84f1bb2b19f35b51203c124aa244e167c3b617055196c1f82cccb850ceac240f654f2ac47dd9e16352a570754793e0bd31831d180712f8d9bca5404caada16508189d1ae13810d6aa8d7f8dda02c759df9215f3b6fbf1a8c4e4dd85a39adbd9283134f5fdbbd6b3afc9aa0bb3962cead5ad85fd3491bd3ecd287aa1ecc35a4aba0d67480b93f2a77d5c29625ecb4bd4d881c2d71c815f183e05c9cd17bccc2d64d7a494788e16d3879bab9978fbeba96d8d4db43dd3b8b4eb74f1b5e6de2477fa3dab10d93792dd9980510e8268af4d9f59bf8704f89a92c4fc0cf6d033dbc6ba2afbd98a15f7597f456f9c4f5a937807ad8c0e587b820a52ebfb2e72df6656b8ad9c8565d9414fea3cae79b9ca4d5bb198646b5a48df0c03a0bd76509de9688abea6ba4eb5c5375fe70fe0d80400a80bc32b95dacd91efef5c06688d7d0ee64a95926d6312e7cb123ec232c9403823d874def67c6433063e6b7cc35d36370bf9e9494a56b67ac5bf74c7426e028175b7da3418e86d5985295f325c435992900008fad5a34dd6b87dee68ef20a7854a071d0ada574b851eba664347ac7c5358f30e08fad055938782236598516b13d84a47351807a164a8b31691036333c984f8cbc223c21aac5f582b1c0bbe193456ea3aba18e86ddb7e449c7248b0f98c99e3cda581920e6d4b4257d8b452fc9a5f99d8a9cecce6121a2c39d315a855c745435b9c5ed1dfb3f9a1a78d2914c297872d0874c158b5b955efa760fda09753b7cc8a7b230ff4dcf4e7bb76845f49097003a563d8d6c094a687d8421bdcaa879aff9daa2c37bb4cd68eb6aba2d6cbe111199f6c7f06bc97e7a87638092b3c71b1ced94df3b6d1ddad46cfb67b41984eb01a8d9cd153847367ce2051f0466981f4cfe6d5a943259f7ef5b096f20125ad04339f175440f91b1f1af93d69c54225306f42809702d33db1e606fe23418981cdcc0645633fd0d6a92ab89c6de51f5e62dbf11585fd5dc020efbe08147446dd3a90c05bec12b74e7e4c7203a945522988247941cb4a72d2f7ac6328cd086cd0db628b80fb714ab2d3dff80f302a6f2f356b48af5bf2bbf260d0d848c004644db4a898025e9bcdf4273e5fa4ff3bb783f7f37c796eb300e3ba49c837f824da289b17933217e693523ac3eaf0be982a07beaa16af1c7f7b0589bb374ecca10dc997d62dbb11e1205c9060a2c82440fee11ca963f6658ad3a2de95d224bad9ca5e9da7c784c21c8e1ec332279c9a1f903bbcce9cf422291a97951324d359b221bcfe6920fd47b9be349a323f1db16d9d5e0d6b7ec0fee2f2bee3336456b027b0872ab6b165df55ddc3d256f74ba3c6594d71be5bcd16c1fc4d2d543ca591c310a2b5f772b802809d657bc76a5f460252f312a9eea7315dc3658522726714f9af21074ac992e4bfe1e59b4f4ed7411ecd0c499d514d7dfca36f5abd756ecde9f90738c7a4de05a1fec979ce06e5a38c1f36025585665b4932a11e706a004147dacfbd89ce0259f48176ab43917e3c107db9bce5c896222c2b4e90f41f2af8b91a6116b370bf40d0232efb95e1c957158bcc1783d29d637b5ef9106d22ef5955d06aaad8d22e4388e3b58405ccb1553d9640b0aa8332cb68a8f531031f6b89c50d5e902aa8ce8108c50299187eb5e52f2b9ea48e1061f709c6d4056c333e9c3a8e04131f65d60f3d10381528eed8e90249d5144c55ff7e8cfc9ed416e0cc84c5d8a66cad90befbaca58b478a3b9b9ee6ae77dcb4e40730c59a2e0365ac205a687cf1d7d076f8d0d823fa021cc0b95a1e4b82c38034d5a0ccc4532a714cc6a86601a4f9cc7202e7b7035e19c235c22afee3b46ea3d25cf9984b19e0c95bde6e860c87a85f93e54ea703b6695f0845e2d6533092af7588d7cffb8dbd438a8e36a404742fc48a4c60e804eca994bd055e9bda52829b06e1d0f52ebc4e125864fb50eeb3f2fd64f824e9f1539216c2a3a77d9783aede89000ac57ec73de830f80e88e4318827e642df18c287a48da17a4a6678f4e5bce00133ea4e44a0d72bc6c4d0b7201898dd5b4546d2fe356d9e6652432baca68a64228f34b83a6e449600e657358cbe0d806b720bf8733496e8494b87e1c7e8169427ff766a5fef6b2bb95271b6d7f4d38bcffd810309d9f48c595e2f5c2aac29bcfefb364f968836821251291a96798e22c10be1f8f85d76772c5fc47b8ec9e11cf145e4b55d01ee04b188cd9a8d4f853a7d7eb1edcefd7da7d2c2ee8d15e85c773d3dcfe12078ebfed1638fcfc7e0f8862913a8e5d07fd636f172521ec49bb893afdd70df842c5ea037703e82244de60ba73b31003cb2f43f218fe8c2ec619fc29436fd18b9fcb4104112cc40ef32b3e0ac6193749525ea985c26afc1a74d4cbfb224723fe41461e8d53348a7e037b7b034a8048e77daa15f2b6f287cfbed5b47b44bda17d824e65307d0fc19f842efbb219a410bf1699a23d99b97eaa170986b36bfadbef971c695e521eb1479b58c91218d77c3db5e1ddd9b1641e7370e6811d99ab31b195cbea6cc58e83fdc2e1c581ab4eb26430619c6cd2554ac653c3c3a4c6c9512a3fac60e0a2ad6c9b7a19ee842c389a6f3f117bad4dfbabe18579fb57f50ba81af24752b8805932a0861d4619802d6a63578133e28759e83ffd38178a54d5ebe9da73da6843d2b46c036ca3aa8bc8011c258fc78ca1a8599f97110fd680ec034bcfc68541b888d0203bdd114f5b5ef5beabd4b15bf9d22a8bfa9b8f6cf45b5f8c18c5bcdae292ee1d670f4af815b5d526eb5fd61c7c922aae684b35ed0798e7f17944531a3152aed21939cd5802ce1d4f096874443dbaecba35997c2659c63cd1b1d0b77612afb1a4ee3557af56a39058d1df6b40dc7e1ef251caca46a9a3d5e4b5cee1ddf2741c82aadb00304b5da4f0d67e95d6151da5f306e3dc26d6ba8ad756c803b50cc148b8ca799f5010e93dcddaa1d9ffd09b42c73896c3d7ad5826c4e69c9dd70aa45a263d87a96765042ba99a4cec7dde97547b3e8d03ec203557ddbad84596b9204bf7ed487fbe1c31b3bb627980cdc286b0158050aeb9c5bc10075b79c0f768b689d1ad33a0d07d60170bfd10bc142ba909f2ff998ac1bb481a7286fce496a84de0ce3be6edaee047d4d5732b461b50d610f71e51e57552eb504c9d1815fbe8be8c9d088fd1ad583189fa3294714dceb0fa0f8002033f1b67049d67523622e4f99fcd0c94809a6d2278a0f3b55d946abebaa564b617a23ef356394516ea9b3ab5610e1688264464595c35e426ff17402e0dccbeec9c1bfc44f8841c526980badf5eb65f674e5c8a90b00375cd71a392c02350a0aa8b5a60eca86664a09fc0ac79e2960f3a8d4920fa9e404e244708e12aab766afef5651f4dc58501114f92b765e19b07476736f6ae61be595f09953c620a39a12542993ca4c7cede2e2815c02b3fd78989c09feca52118815470669bbe88bc01f372755e76bb30e8cac7c319f8ec3ad447cabcdf42747adbdffa8d4896db458b4dda5f776477e90c4c6dc2736f240abe897661fc90f07a6134d85dee40a357c96a05a173f62eda382eb2566ea0cb197cdcba34513f0b7c2b4bafad42a138fea2c70f8bb2389a5a9aa16bc0df4f3ce37d1a9965407b90ce60ee69e31ff3bea22fdf1db1b666d692b9fe647794d94ba02f74345141bd12448d3ea85c5b97977b77fb5f85f7a773e06515ab8b9b17ffb630ff6ae5a0b95155653c6d71ff9aeea4c1f96407addcff8c9ed27426fabbd5f0a7817f01f57f594d3daa8639b575d578d0fcea7cdfc88e4e4131b3242919ba79aa1dec6d42763705c4363243004bfcb743639a66ce99c847cf0e8e4e47f1328b0e16347b2825a4b8a70de372a9769011f104cfd637497b6c5e3e7b12df22859c0caae988b8c880fd477a62b089e9e7015480a6d53c957fa7a9244ed236177fe5626f4bb33b68c1e3e3e754fd71383da928b686a98dac20b0172f8bb2929b31939cf721a1bbecef96f17a0faf38f8fc980f8e1cb9c167a65e7de6f8f2f506145c43916a8fc65937fc3cc9c277b02c3928261f3936bac25d9116f08870520369b6f6c89506d16d78cf99e10b1c56d228166423e3edbcaaa7f026f852142abddeec6a0f2a1035aa29c2efbb11229f51addffa8414e9b1359410d81eeabab606ee7db78c1aab316cb9f3ac7b2d6aac573ebc4125f06fa7b2407480eca01a32f75e45202a0ea27bd364dbcce860a964a437103656c5cad2f8b93b7fdc6c0ec93dd399aa3c6a0e9d526f7b151d9ca4399b299fb2041ed22d0f6cb192ef4c24c9829869005452a7c997569953e85cf0bc7f9761cd32d5c26b95925935836139bc5614c45db84ea3acbddc11c9d51c2ab1f45247281c031b2b7d1ec5ff80661682fa1cc829dac811f13e95b82d64b3acedcc105a43857213cef7f91cefd49d8bb7c081" - }, - { - "seed": "478235be5d012c3480e14809d6d97976807d5228e9707c5cfcc7686b0063c334", - "pub": "65010069a786676e4ed63fc2da37392c15121c346fa69ff19725b61131b6f922f942cc146705f69ff1e696d3ed3ecc29d47197882fa5f161717ddc05978abf629f3778e061dff2118f48a9567f20d6a590369db7dc04ee8df483df5abdfb30317a3ad53f5b9745e8d671c7cab9c47f96a7e4c3fa22629f33e88b4c6d9e02d07a6a605ff26fd2fcbaadc2834034d452cd0dbc868f853bc6a13dda6e91ee2e26a6a1fc2326ebdba2947a4e84cc612e299f04a7ddd1871d3122d0975e41fe9a12c7d7b6d4bf2dd0ebc9fed358c1f9275aec250a3a6ff56d3f9e1af9b9ccd8260206267e7fa1e6b4b6093b7dfb2c6264cf9043754cdacdfe4da9969cf7a9715bedafb1e4760247ceb2d98c69622f13bfb3571e10dcc2713d9d0de82c06fa8e66169be81866c307129da8cf1676561b823253d862b956766b282ccd661a239ce48dd687ea3b2e55562c09a30c404e7a45868ebd3c9d51732037e93694b97b9977e4f91471cec37f182802d822c78686b90a63a9ccae17ddbeab1553f0042eecc0324b81b6313b5110937669f29e0b04beff8b779ea7e2c074ecaf8cab43b9cec123dc410e363363512723429bd1c30a30eecb70aacb3ddb7e39056d13f02580e34644f7503a12afce7503b76fdce14d23ec2871f17fa51e13078a23e9232bccc88f276a43175db7bc96638fe374471fe0b9e974c495ac036ef2ffd50dcc1f22f50a901716c7e1a62bc2934741d824adc54290ae038f8c6856ef12a2e07f39e1c5f382c9da924d020570fe3f453bc5b6f2800787d52bff3ffaa518a7476027b969e5ccae62d729f15033e76da7bc24a252e327a70513a3f5b0e02fdc72aa09b78be25b10ab5ec3ecac3ccad986e194cd856173a6a0ba942a95f110786cca7bc9ae6930e2920e65bafd9fe8dabd9d6a2f4e263219eb16a36867480fccbd8542beee3af7fd3fee64d8be814ab7b306014517c52135c7636eed4a91ca41df3f0f9c1716e15b8b36500fd8766a47761a9554430ad6569dfdef5200e97cde0f677ddf538101ed43b449eb40589d2e1bbd6c5dc73ffe68f70e0f2cbc5d674e5378db853221c58b0b8b9aae35839e7bd25113afce30f9a0b1d71b17c001fed4de45c46f93c9b19862bec60d38d2ea82b8c00cf2fbb8a13b2203fe0d3f888f44c049281bf5a444d4ff9483d1df83f83114d671623df5726931ff891c73ee3f67272f857a7dc38ecce783e5d726ddce6094cb2d93282409b50a2933be61b3987f8698364fd2596d591bb014f2369e53b436589251a7605a863bfcbe9901f604c767f678395d3d1722a2c721a37e7230d5cd9b040fba5d2a9b42d0da332bd22b142ca81dce67df2a1e520f24114f008391c3b9a07422ac9828b255a70603dcd160092607fc61fb393d155f721853411c577d19d7d3a934c8b47efb0ea000b46262f235a587046677fb125c59144e947b88083a90754f2a85bc2e0c7629870a871e198807ff18553a0cfef31395361e98c0dc8c3c11980009b4741c487b4cf447f69b3b4afb424b295d9c4837c8058d6a28c8c81da3b4ce7c7b85bb8ab15c3735916988901baeca7bb62fe0fd05cce0608bff705188fbe2bcdb08222fe972f1a0b194ac2d7eabdd45f585e97bce424c3d0ab927bafc0babed3956ab88b87f1a675c04d5ec551090bd58cbbb674beddae4d9f6fca35bb1559bdb4fdf9317f237c3f2b49e1ad49c644ff4c2987873e215f6586b8d8a68acc7246211ab024023236228d1ab9ddde7da1261ee00a247689afd42eb7bda1ebe5d31cf45186db2a2f16767926e6ec199d6c4b4e503b4ac111c94157911cc314db7b00d9c6e82a5454234f71c715b036c6d5ae07e44023af8f6df63e22df4e628b37c26155556cdc760aaf998c36c075eb1f5ee78ba87cbb0d7d7476d2f550990cb871f94cf17a436e5c38b68143d8d95e73cc2f622d13e9addb122a98e712f7be2c84b48420cea1cf1236f6ec10a60a91a40a1ede85cf052eaabd0f6fa5031c6f74158e056d83443ec01ac460e5334b74545479859bf8d3710c1f1383d539905b84cbbbc24aeed8717532ec7bfb50fcc4ebc307b2797f57cf9303a363aab2b9e8afb5049bba81a2e5bb2f2a1f292e853d81e9c4e997e1a458649b628838a300f7b570ff48fcc1382c56486e7689d8ee23f3cecdb4333ae0887f418a689b3da7ae6a3021ee1cff753f46e6931ecdeeb82ec907889c1e36f19c67a66a38fe6506a49b6fd4ba3a5fa7094ce9afd462560e43ef33e337d76caf26a39a68d606a613fc23f68789f92cb56d74abd85509e365104f022019414560427ba35fb8819b8c3b850009979b601a00b810a0cc593a250beda765f53af53779e0703cc4fd30c0b6ac18152cf5d8fb954d918d5a3414234d09bcd08e9f151ee4bd96f99c142441a29f71ac2be33549e0e41804ed3a016bed83e315dee3965c01b576af75969c774f40cd7114a39da66cb5147a153126ec2b3880a5d3a515d3b878ad62339dcd39d00bc9b383e12056917dc3e8b86e4db1d6b9f77a4029ecbf684990579639af8e996cf067e5ca3103c8e90c0988c5e9ee09bfcea22189af0101ed73746b1661423bbfb02d4fb3b19aea3aaa6fbe966dcd91bedee468990c3e07f36e7121f19b7e21db6214039b3b837ee4f2fa28ce9b44088b6bf5824fc749800422d66579d0ddc688be0d860ee2bec170e65e9a8026df6ba61e3905a00b69d5feab85438017d562a2289c80b2dd094b66832fb1b22372c2e9a4ae173592844f743d385255728ae5ec9838a8ad3bc5272c7479cf2d656e0891d42a5ccfe7a128abe2ae9e92fd4b43f9117ec355c1fd269fb338ff28da354cb8f5ba13831967a67105b63e65353348c3852cde0e0edf7f09e57b1351066193f91a832eb6fc7648c724ba382eabcd8ad1d6752366ed8801a47f1a71873e02de1458d23b22d726533c0eae044e42ac9ebf7312907bdbb6f5f75c54998a9b5b1a1fde32f95433243a8f48e5a9698b8289f4d5b8b63e5907fb7d11af68878b24871986cc453925332c2a354ea7dc69255d8ee2892e646426a8ecd5a9b1565638ce0f5671d46a85c7884174ef32b2a317ed058910bc128a381024995f02aec204151f4e05f30617dce1dca87524893d79abb74a1bb800244ad95c3d927e1b98cdf884eea646d09d94674c56d54d4259d624619c36d7118654e6410469454ff1d2f5fdecd57a90d61bc66f9b5a5628875a82599def4fa8c7f36759608e4a2568f445ec48df67f94b0078f4dd8bd5aec510b195c83a28d1444324432358820d9aea5c0f96cf0e0fa253e7ececfccf939b7e393be10d5cfdefb6a2e14914e8ec944c872ec3a61b72ee19eb78e2c86f64245b7cd4384ad48d8fcca5527eea55a9e2ec3ca4df45a6301ec50948462ea50edbb7f89f488fa5ec3e22406b97d340068c1701e3a01884f17d77ea566904e3489e7f38c1b736217614297dc95e46ca827cb4572ef31b0bfd89e9c7757b95a7c46979e135826447c15d2f8a0084ac21323b0433235b63f680a7f1fd7d9a06ee17608ef24982e61c09dc1500323f24f3cca41d3385216c1f4d0f32b52c3ab7f21e9a5e51f44134a5cbe8f56d43e27b517c31426b94618336575152ea8a31c283d56288ed97c6a7fdd4b5c828fec93145da6eebffdc4", - "priv": "65010069a786676e4ed63fc2da37392c15121c346fa69ff19725b61131b6f922b9ff0ff3dc850ee15be1883d52e0529410852a0c1fe8150106a45af5e01bdda8f9189a00c19fd79f31e2bfdc0d9bdd2075a3b6605ab676680b71d26bc0dd4604b7beb46d8712354f173febac07e27a151238f0729d37b6fc071c40ef943604ee1bb5859c140e9c38110c45824c8681ca0684c22028e4342c0405260810409988885aa865c0b085d3106ed3b6294a388400b98dcb083221a861d042520b124d9a265113080d214661d4180ec3308adba64dc81451e3c810934045a0b609c4b241140042108330a2068e8206081b953041c6700a40915cb811d2c40513a828d982204330896402318a4249e1b4901b1811ccb20140260ed940410b9031022191db124662001208117291849000b7686384692395454c084ce290281935325c8420438648c8c251d4b24d84c49010196183220282386461326650466a43408659188ec33042e2148483108a11b305c0b27101186dc1a68402024588a0311334651924020c096980c86c1249704b30421c380a18b32504344583928cc4284a24c3490b4132119989c284411c8530a1380c11022c023372089051cc48001a066154420214216253020921b60583c621238561434248d8c64012377041a85082366412488561186ac0120d4ca62458b0844b2686a490699ba8640301314238698c825089147104b46153024c63c49092948013430a58a809c8388ad042095814810b362482324c043971d2800c62187198a231929008d00469a1a028248069191566601262cb84650a330600194e5ba810230841200904c420865100098a920d20178800260d1a850108240288262598c08410334e031066e0962c22c54088c8691cc8401ab5104b006ad136859ab0451181205b022293164ee246841888894a840010a3650c884dc1c465a08408d12844e49661104681423260548645839289c3c00920294a0a99484b10200831661a106e1b454a00350901b10c53204561b20459206ee2462d1a094820282094b4041cc30804088e0b156d923461622651a23040c2c07158424240c2319c22844b380440a451e24880cb807002436dc43608e1908109a11098a08c10a3911c386aa3006ad8984de3103043325188b06904a7101936320031525b204ec32492db868cc4968d50024858b8710c391012384a5bb030c2c26d19402c9936711b476e004022a3009000864d50b86154388612c929d2048549240608a820d81800ca164c22b1494a2031110321d0048e0c9748e41686c988109898414c429184826154a68922b6401ac70c89146c09a5509c18296196294a98090890655bb0014c164183826521274e5c340158244221394223230018c42c8b340959264ee24090498044534611404246c010410a0589d0408ad0a4899bb6211209099042110a186c92c608c492481941401b4486e480280a392d64302022b36863a44c89346462308143064cd9344518138514060412b8050cc4701345291c43901108051a288a030005d9448109860ce1a64c04882d08a944c434280999490b988d94244204062d513085994872e2828008304d4cb624d322010b253110a98903316cc0a861041951888231120409d2028984262408c145d81825203504a1360a22240e03322a1a433054b26411300109950982140c4812801040326244250c403103894821087024c70984080e08358001a20009c70003148024830819820d14282158323294300181b26ce0a28cc842201ca8309ab4481a3989241990db9691813206da182aa2a090200726c8288aa3446e4130109c020609a821a1a250010224818229021608d116651c4670e100921c3884a206624236280b9680a1184519b74143c4919b28250488845c160ae4b62d4c080493068923348e21386a5ba869ca26320a228603801042b46500108111a68c60b201824246414861ca080d11072ce4a2914488500839660a072a44c44909b34561844801a74121b62122896d0321484892244ac68c5480840996245a282011c7511c334c0b496508472523c744401008d0346922c041593090d9968160142290420404457162462992040a9bb24813280522a4915a8245998281a386900a12250b494449200409904963928d03974de0b82cc3a480a330061a01258b384222380191a244044201810842c063121afdc128dc1a46c5ad5ad50df22f6e0619b29392ec54ede498913281f00e8efc629a0bd8d54e82fcfc1141b7d2e1df73c9a7bbcae3be41f5a47ea62b6d424d4a0f9268e17c3b55a846365cd772c5aa1f328ebc10a4a7926de1f3f4221f8a58966dc3c4aacd41d0fc8b5b7b4689e1e7dc1e61abaef19c5691040d62047085994fcd37ca5f71848dd10c30a5f1ec74d8284340d698573ff13c9ac9f4bb91cde61832b3d1390caf940e34a0a7424b42a416e83bc83795d51fac49aca66a1204036a85809faa751ea901c360db8ea4ae131252dac625c0c303c2ecb8335344a0e56b4476ffd83d1d0a49d82880fd78044dca7875a58dea12cbd493e612bb523cb4003fa7ff44b15b2306d2f8737c109fdebaf4e2ef36505659e460f6491f67b50aa430e46c8c9a8021d5d34f27743b0d346b6462025728608ca53d1b122cf1940cbe031d4de2d330c806e9fe7296ab94a8016f9ca39b9a885a2b1237df876202b699cad5ca5bd5df893eae5a300b253a85141ff00fa9a1eb173a6d656a0dafc0f1f4dba092a1c3f55691673cd8efeca3a42e63d2f9f972ac20dc7638f586426d7dee0affdaa911dc1dbabe4483dcfd0123e70cf555e373a963c380925a5e32a8e710429e31da033bacd1d6eb44030bcc7cd57c2ba0663e31637e4a69c31197901acb00268a1b4bf5fefb64d3e193936f9f3372dd9333bd308bbdfe8683463a040f269229db4d1794cc9d7f7c26a019fd59e56759731f8f1ae16f371b549e552a536ff5de55be616348e188a0c01c5ea5aab585770c726352489bc4a8c2481b8bfc5390063c1c467b269b3834424b726c51f28d57fe4d18a9855491d2eb3a26165e46d3ee64a1b2791ef425845f2beb565350590e0916d9e87ab64847e18374e033dc48fc2235e5323f5cc24a087b7a3b36171e9c885cb78201cc304bfa80b6fa20eefdceb10e16ae31759eddb247289f4f9013d77fe0a1aa46f7417f3be9bc9b4cfbaa24b02dcd37cb502f41ca6969cc748997f9fc5ad88ab3dc07bb381eafee616bfc6b3298245ee24b80936bb82a7fc9a9e19055189f06964e27d5e83ee00a6e8f30e6965e0b444a9e67136f7478a74b9b387b6f8639630b26722a0b7166e65aebdd6bf86ee1d2ba4ffe0f3b4a9937b5eaf02353a28adbea5331189865204ab18aa23cffb563810ba25944402fd0daf3bb5989a7e03ddf327f4c5bb233e7506cff3e13b7855ac2f6d8e3a91dbfed0dcd428b5cd4cf85a8a677a6f2cd9dbaaa5426eefa97d8ef62b1d4b61a22b49fdd4485f097a423ba604af1480661d9e55ddd6f5c6f3b66154b110ebe62c47dbb6f196119a31aff42b69ec370f36ca902891135d79f5da62855c1b60182ada2086b402dd23784f649a5289f6b2b8e0021fbc5061a953bec318d5f11bd8216d607998549cdad4b0eed507ee93117c79d611231c5538ed45541bbd5ef4244387fbd96a88426f0a9dfc450679b7b7a60b81778cb6c925a657ec23edbdd34721da627bb530d18ed842ac8f30bf02aeb1d09165b59cbd59b329d9ef20aab77d1ba04e6fb23b31bcc1c65d32c54704df26c1cd560afe336f11087b8bee67e0f42845bd4b81b56ac1cefe479536e2aad0131f73fc3a3eec75ee8a142952e70bf3c8a88c4c1f7bb03c6171b982f849d494c72947282c0296519199966f08efb7db2d3341ec9c03b7a3558899541ead858098e0c29525d6a612561c69cc88737bdeca22b492320816b0e9197beecdc727385d386c6b03441c45a97c8b0ecda552387d6791dc2fb0f39d0a5203c05478f7a79d0784c8b947c9228e623f65cce62b06f78b6ea04115fdbbf4f09ecde3d08b9bdd6e0d3cef172767e0e9d060c1e9e1d29f68c81f6c975cf349c1b1dec8e4733c2b1877a76838e8f499d6184dbd73ab315c003bc2dfb68e2100a7dfcf681c6a57d32cbb7c2199fcb9ffff1b8a4aed1606965e109add51b17a40810ebffa8977c40b9d9dd05383bd9bb8601f1996b756dc7eb2182915158366f3bc255b8f754f1f3d007744813a2385b834af1a788ad0d457df3fc5ecc5f78033279e38890e1b666c7852458296e6d211746ab11cde54ffe7aec627790a160bbf84b86a80527f597d16c0f9be0933e3e5b1e7b1267dd8a978d6458f942013d364a0c4be26319728e8e06ce7dec99238ceff4c0baf6b2543e3d7a4d87097067355aab430e0493abb0b2bd3273a43f7bc3f1fdd28f2a9432502446d5a05750aa97712f2a2970af9f4cba06399a3f52ecc6b2370908e13f8da223676f3811893af0daa588f8d207d410f0b22686f2ce5cfdbfe85f7cccccf70318f6d157be70f84748cef6b9683633255e6cd7f2e83fb83c461f3ee530402c3beee01dbd7bde42cf0197af9f622dd6850632be459880713d227e06b6123def3fb7472ad9a4f0f413da3618668c34296264e22994e45c10b0650269ad4b4e203319f5d6f5f5affa4595c87552469ba517bb2d0de7df8e1e2378277e7fb88d4b87a06c94d09eb9f287a2cfef012b8b76990e4fd9a0dfd20b8fab20375cf5ee084c464de762ac83513200e98a01c932abb79dd8d54d0dfb7cc807dbc97434c64aa1be67991544f64631dbc11b3856eff07545b3902be35a56e6642d3fdc6238c763257b6a21197f3d7f6c5a610d8925f43930fbcb13e1a52a0e6b252eae6296ebe4fb35d8909185152e459105cd3b9f2e706be400a44ae14cb3440b1b9658c50d5b83565aa11521c617b97957faf5a5008063522f901e244faf9e341fa033d0e3ad2ca71773b584ddda842f6a74a08a6c2eca1ea5f9056b763b4864108ab39708498bd184f0e100b54cccf3d75a3157e60d4c1dd67ac29c78fa7a38b1ffb8d6a5b244b63718a28c51613157a2499b0565ef4936f3123dbd8b24d027e92175fe7b31d25489d121811cd2d0f292f6758e4dad9b056963efa21eb9bc1e9f778968f069493d4fca247d3902642a5f8e4e4f1a4c6f541ca6e0663007ce9ab7e5788b45bc5791e70ad0d27c51c38dd898ef28d4cfbf869d15e4c3be8ca79b3a109369b4c1faba03d0435938022a00a33efca58b0eacea2f2ab4949679b9c4c9b7db00e47c433e1cdb699c5827ea144ee97d09df46ba6525c60545f5e37811285439003ecbe8b260d5574911a4d828be19634e1c5ff94c6870fb5269fdb7d41427c2142bf112f13a0e8e09f9c5a5c6d5979f1524913d7d7bbf73f87db2cf6322177a73ba581542718f5f14021bf59d7176d96a49c89e79f29cc515cd7da4b9a7d9d7fbd26e186aa5b60d0e7f0aabe15b53ba62345e0a450d7e57a880a7933f3077190ae86cc71aaa7ae443329bc6ad46db1972b578fb04e352126370fddc32c3c39846cbea8bd3fbf510a736ed7f931efb16d329767570f7efc74e1702d8f1d48e65480d5c6dc7201f6f0dde1c224f72dccc383d86c19036463a22df089f90e63e06577a6175848b496ca56ca8b6119ee778854efcf3ee3d7c772253149b4804f02ea8076ba628b71db6718d3b2f81f580673da70ceab73f4d91b9be9d913497ee3ee9b2807528e2495d5af4bf6ca5f2e6af4d084bab9ce184989f9fbab003902fe1b0721c4c027ed67e49da035e0092541ebcd9c0b42ff9b0f6e36faa637c159bf2b9d6ac2575b90b93fb3a8f31aaef3ad1d9f2d2f127705ff44c0aa22617d868882e9320fdf682b86643aac090c69961c501db6a6d7d9cf5439113c78c04ec7c3d18efd6256fe74c273595b56e972c4655cd26d86a086c7018c3d74197ab005ae85cb75b325324e8b3c5229ab15dbd3ab4f4df7dcb8d9f4b9ceadbd8ac95db5a5cd679fa543a42a465dda2d62e6655c2dd5fcaae0950b5fd38a464d87e00cef5e03e4396a8ed818b456982b3d8c132342ee5bfb506b52d2fb5dabf8b095b9bf7f5019e6bd758797f1538dd5e59c0a9f0d31e64dc353c4c1527b98411168c2d308ad2da8951a43bbb44a37fef63fe15b9cea6633f177ee9632d72698721947573b0fffc9fb2d61959520d2f784fe29bc703bcaafaf7a1a0ee86771447aae72be61d15155f02c292b44f4e6652f28a85855f1184a64a88776079d697a489222dc3f911e74ccf1218268c34bd0d7b368e29505b56b720872916f37f0980cdf9420cc2c14b9a5eff1aa931774fe811cbe3e03c263f3643debc7cd21c2926e9603a782d950ba5d5ecf324dabae7053007c7a5ed7ab84dc731934ca8d19746b0683a3e4882bae15911c15f4736d425c25446c0bb3500fa902981f144d3321f58fdfc5e4c0092bc204677c6c38ac9b8bae44b313847b8dd185f05f0ba36d7ab91c0f27422e5822f3be0f801853968dc5123bc377488482110fbd3984c81eeec587ca59ffd4976c39db4ea784dbccac5c95b1aa76d113a55b6e4002f7020ab5f38008067a28637666cddcdda9d2bea456a3154f6ff67648b7c5b159a04818c1a2842bc594f623ec70b8c47f82e93d94597f952a35706a8b58ba5e28008c40ff1e24c2c035d9b76d9a0f9caa83764a0f5c9f246ad0143bb6fb05a3c5c5ff8fe50618f2c84cf16ebbd7ec674233a47c7d687b9ebb6885ae3f399a28d39171431985a70861017a55d90c3fcfd77bfcbece448ec4845c319f5a0fbb7e03d36b9e07cb246ba5a98ba2da422fedc13cca6bf720c8600c7e0276c680340cd29e60f130500aeaa8e7f38a0be865a42b0489560fed4972e2016b118dfc96822" - }, - { - "seed": "46173f6c41c6bf3518fc9e1de634d0fdf229cb34e03cdb7d2a596e0b2a70372f", - "pub": "703cfc033f334fc39ab9132400685c9049b16ef017d6cbdf384ea0ebeee301917827a4593f5d362d55d806a3184b9467424ab2c1ab587ac58dc70761cee30f12f4cedb43ef6159d4a4b04bec6dc13c268274059cc59ab6acb8711401f72be1a32b073371873645f708ac1842d3acde30af4998062396dd4a260f868747b5c3dad4689af394558a428d16a0bc10763de7bb88c22869e0c43fe3d0f924b71efd87b4121c0f3c3204c91b15b1f0d1b18a701c3995aff128cb8bd99739207164cb8326f44e279e16c8b94ccfe41f527ba0498ce47215771689b99540b33cef5ae529baae4376d7a4db5562efc48d07e6a1ffad0d7f3f7c805d67c55218ce8cf4c312520091e81afa8be4be5bc7d82dedb01ae42869fe807c684c555956084d528dbf3801fe9e277e93a42429d0ef9addf9a301b4b200d7c408bf0b0bc4520ea661ef89abecbb58e7c509c38087ec733e3759359137473de498188e73306e00c18b9674b0efd56afb1302616a5e2ab198c3887f35a8020dae712ad905e3bbb55e264056edc3debedf33527134450c71016326bfc777c52cdfe0fc5f2fc1c86e377ef397e35512ad9d3c1c9ebb234ae41445c6f957e6f196c67c6bfb07d6d4c69af3bcf18534704dfdc3c6be15d41c2f13bf374496646f88f94eed44c44c71ca8c771ea3831aacb2c5c0ec6313221a5565ea3e3d3cff0f7f6b868d8fff85bbfb0e29ae710f4f044ee26b7c8adf50ebdfe49fa4e85618784ecef4641074b527bfb2cd7dd1b7e291349706f8746ba598a2d12135760266eff7785b8187a2084327f7bade92f35ce8fcb13370da6ceee03bf984779fdf67c8fdc536b86868080d64f24bbe7eeeea53cd56b2817de6b8ae24dac37073646b1a009d5900d0c68dd93947c5cdf047148ef2bacdc12d1697d1734e57e8e626b95e3bfca4a377d4f6f954d311c9ea75fef6b37fa98d9de3bfeb46d1e0b253912b623bc6e9a148fa9751e3033a143f7434a5ecdf495daf351bceee24b731fda2f3ec5ebdac03ee5eb061263f01681fbcd529c488485147805300be4f505e4051e1d8a4d972ace324e9daccc745faa53c83a64af5eb6ed0f55f7500c19cf5ef32449c26a0fe0c2ce133048dddbec664f390839fd6df631911860d57d772d4dec0e7c173ce921cc7c4a4298e6e39f3779c6c9c04f877f0a357fedb78866dc8ec55b72322aa6a4da6bac02a10d7c20f388ab28d7d192dd02a96b2b134cb2a668072c403dd89114496876a7d175977b6fee4c58ca3bf2083e178ce65c55339b44dc07276ff493037871b9db78db18942a5ac0fb0e17bcc3092d743ec561097e606aef9ca1604670ebb39bf08b7993e2d315417546960a276f698d3aef211c87ee47f9219ea0eb92a1a6f0ae3d4b7aa822079ad60740f287379eae09df9ea934e69b67966eb737c298714648b0b464e5c7a8b89030a43134980d180ad839f66630509580e084ffb6d44ed108a012ddad05672527ff7d47e226ce7b0e0c544d561b70b0f68e2ff2c5f4294e265e007ce708503a187ead22b0ad922bbcea1b9943af73d41843cd13ffec29df024df20a1e96493b4e19bcdc909415f2747131bc9aeaf43fc2c64a92d44ce21b424e2ff18be7fd5f797a49d5dc9738afe7fc935cf309e9e843b023df49032b2909a896340a5a938d1cc6140375b592109843e407ebc241764cecf1320ea079d6eddd61a472abf1fa4d42b74c5b1494bbd11a505dbf8bd4522118d6de5249aff8d682355b9f8e3199fdd2e6c40a7c570d5aaf8f1662e20009096ebad875f921a9a6d72e538412ea9711bd42ab46f905f23c877ec014beff7563451560fbdd0ffc6cd36006334213725b5f79ca1dbbf6821ff6684d4e45d048b7d6263453efaa6910da399f98a18efb5401296153c412e619c429202bf613e2549485ef802ca6d4bb2b166b4ccc27e29242177ae1443705ff9d705c4dfa73542bdd0d0fffe890fe89b123ccfb6c44c6f44586058dc97150cef182fbc34695a5440dec314ac71172260ba70c41750fb4e45676bfa052c952c8d9110f88fad8e3b60f2b828682a3a5830f856411ae28a0d174cedad405b2b2d85b21a0da027bee12a15649457100cc9e9c5c65cd924896cbcd9e12e71e24a89b01bccc25147360f942551fe9c7ae7f747c68dd1bb9d92d74395453f7741c6bfde08998f83e2556397723a0a6814af6a95941b2ba02dc19c21a0cc29e7fda9d0b5b64c8e6f6f286acf422948a1ef67f792e744536fa8641c817630abe9e8240eed9047196867baea20fa3a1f66f4fe7ea5059db9edf96b825933ed040ee7d833c64c002bd5d435ca2945c8fc6534db24f6bb8714e4fa3e5e94688ad1b7cbc9bce498996508cec5340d53d8db19718d41742fb056dbe16576ceb4f063e75bac02448db04de72b731d5a1a53a6e6bce0c13482478d4affa9529010cd436754cf605d4867a7c98b6ac135e56d55a61e69c85f34262c16178f462212fc656ff3b2d47fcfc955dc842f3e7b74be013e20f1216dbfeedf9010ca5091e0a5637b0d178441730ac0255960202107e885ee2d80b2403ed21927bfb66b7fbac7c65fc15d5c076f9319ab7bacd1dcdfe0026eb16e202817b527faf7535ef0ff4de86094516d4ebd198c89e031aa7dd4638406d9d91adb7a2e998e2d2eea6332a1593d9014f7cdba6162e7c5e3de51f5533c6ea34dd72e689c6f82284f140b5caa2aa01e48d88336bb0d0ae2df0f9d850277a4b4153c68e5e54ba957bc8d2721a0c1c28b742ec86fe6168f8a81da5a72e1feb0507203758c37a915040ed07cb3360afb90205025fa4ac9574d77c781271adf17c3d079d573a7dd14f6c750295177d5a54acd7ea046144de2c436544da570018b75bd767ce21e5e2f3be156aff9082b67a347678c0d31e33b8f975be105ce397be562cf5346ee1e22cb3ee55ef11d80e4b87022d426144d515e263199ddefb3b897447babc00ea1df6d78bef5a534ebc45b8ef61f52e73c488ea9bc06b042f5e988b4b7b1516b23b1ca6cc0d07593a52b86106d05aba5005c674ad2e0d2c89210831c05197d072b51a7e28aa14291f2b7fc484406aa64797d5573e442c2ec1b93565ccd60436432673607f0e510319dc5f8cfd2aab674bd04002c83feed0132412096a695da9fd5c27e575617a69f3efb0b10f2374dc6af7628a7e1da985d383e9bfc44a59bae6329775ad5b6214387c8dea0b75b3a912fd2e1edc4978ddb73c59746248617d47197d62c92d076db9173fc0a4cbeaab6ea10f6cee4dc7cbadb3195ed003397e659805f775b76eb690cced272b1bfdd10f11dc6c35a8fc69f9d41a524559dd4fcb95bffb8ba2c2ea63ee1fd19a7fea50160c827cf5042a03c519bd246d3d8dd660fb14adaf422c3dc0020e8742c9da19379da0354075b2855a9a7f346b28978376dc2568ab78195d66b418387a74f3fd4f74e117f3e75142b0a2d85a29f70636316e56a71390d05d09886923bd997d850a8e7bfdad0ea6e19ee3960c9d73a04a924e96c6b2147278d99ab14b6c8dffab67256db446ab3d017dc1b4aff9cdb470596424eca8859bb926a279a521dbfc59329b90e8ee7834d86fc0865aa77052f2c22bdb2d3d5a2c19af570b1c7456c002854a2f699931336ebeeb070f20b6017e2adf3", - "priv": "703cfc033f334fc39ab9132400685c9049b16ef017d6cbdf384ea0ebeee301913a81d52768c6229e3859137b619ed8e6a687cf0e462cb0578c01b0a79e26135eca7aa64e76934b3f147358af0e07055fa4771a35a9eccfb71cae73856a0b21d21fc11935ccc08594e3e23a57643a1ab494e1ea9638c8b2eb74bd1d1362888cf29ac60dd2064290120694a4900b17891cb82583a86561108e21240602b68d020206e33602d3103112148999c82d0b9028c4289013376ac1842d5308122413085bb85119388159c0698ba065e3220963222110140093b2405b066ed0b881d44065a31269dab450481871190364d0068803242188466480442e21032cc9a285a0c0259b14209322400c32884a3644244532c8928441024d14334220064a91286de4b4844006101a23488c42641a356281a801883891a0204a24c66d58c42c0a0946cc366520492c122392e304690a00729302029cc43001c7650b340499167141283101055011498060122c13a20c24120618822810c94013238e62280d1b11469940842122468b8045503491a1226213398c120968d3980420215113926102396913396ea3b21053b48583282819020194460c192750a0b2651444514a2604ca120e19c10c4824220843321b178c4a224148a88c9bb045c4344d63226d4298089aa82899c2801c347011922c02396cc4444c21a409d0904514158a4aa6311847000c9445e20664a236454a1201e3b86c242632e480491323501b436809204c0a118c604031943840c4942914208aa40012d0940962b26c99a44148b660118060cb360c9c887002224c12148c99067120839148242ce4148994444a1b32515c388992b631888264cc0845242432c4384c10300a89024158460e092865084906db8221c1b02540208a0cb5018c328e94066ae3a08c002825d3a60524018064a85162266e2480211a0841422224d4221118b620533801530404c0000e0b852559360e0882054c4080a3380190142acb128e03a041cc220803308a18430543902424a4691b005048484909432658180e23a404d8822c63444282b291c2904d8ba27119138d9a040d01b0300804421396640b90089242601cc48561c8210b2330621085d9a40544488c50920412b984d0381282044822a290411086e046811c018aa4c0850a944420392a21468d81b60cd9363291a8254b04804136414ca48504922c234052c8120584148a11a1491993619a1845418031080686243542e08421e246061c238912404602b391d1202921b1048aa88c58a06823264e0a92891091915906041bc004da10420339690314094382714002861a876008c7414c3600da2432922840e28409d048812392850387040ba709990864d8245020b54413424d1800411004219ac04161862802c48c5b220eda044519922d90084913938c43820c50b02cc1384d40086182a02c0a0681141572da3209c1108c64b461d9166864242e249468030524514825d4166920c01062409014496163a88c8c3820498850c3b68018b02121268a9980259a189149986c4b042810978863c2048bc681d0a86d14c92c9c4868d1940199b028d424454a866080444c243170821422084760118369e486859cc031104292121886dac401849890603485d280702232041b2148cb882d08408501860d12394ce440089b247104b7885ac26818a951594224e34802ca166943108808160e02a10c1aa188d9424e421009c9003008826004c76d9c28718b382149222082323044388809b38d00177160c4295a02695c42299bb4695ba4659ba08d203705a3480d98160288204258a68801b920810848d0920dca3421028820dc428a814864c2486090444881c0451a330210336000b820091640084672618884111025c1c86d1a0402db86311ba5051cc97143b848cc4605d8102dc1386053882402914d13c45024408ca1a471a1468e89a08c6088841b162c8238419c1851d03200421844d32631241569e308011a979159380603252c18b620c3a061892222531266193731484830114940d9c609a0c04c20318984c2656006320a414621b90d894206cc968c8ba67148041189148ad28208433624584871e1180cdb3452043470944649c896601233451b146060406a013688e2448ad9c404939065e13029d3224d43907164422ee3402e229511e0b689e1a08c5a2885dc346094a868dac7af6e25f7559c20072927a9024ae84c6d7647d5f5a5f12da9208574f71723cb7e9aa31951e999d4c4742f3cf91a7168d0d15e4d14046d02fc6dd08cff4abec2357716ef6ae91e0e1ebb311b26b26c0ff5bf6fa58455bf27c3eeb7dae5863e7be4fe30ec6c7906fc495f0728506718e3092aa0f21250430b0db23d63a0f2f1f64cccff690b567befe858240c9fe3f4eef22a03638fd82d0045fe738392418745d8357ac507bb1b0cb96181e774659a1eda5c8b4ad75976858a69923450f7287de8f4e0a4b725d2d26c3ff0c5ee3632a7057dc3c1b7d41d206ed5a82da103f12a461fdc5377896b6ead473ee38a1d479803ea9b044a778425aa5f97c37770786ce7694abfea956a0ae4f493e92d9d62b1201c739182babe234e73131de5e1daa00beab45cd834f56d822385cc3d0b764360984d2631b40ba0e5545dd77f87b31b09dfc97df0814bffc1fba4ce5a1c50f56c493148eb91f1d0b5233dc999037acc856ec1727446532b4b2efe13868aaa8857125ef3dbef8a5d99529d517ce6cc3f2e82ad95c0811b45bd0b6aa1d48e146696ea0cba2b25b7aabeca1c701a1c8b9f43d79b9068a252e2a722931e56f6364205eeaaf960af74f0eddf7493bbe8d6abbee4119a1dd3e6c1fce45ef4c4f902a6c0998b93025c84d5e870c8f2608f2c1ca103f17bdd1c0fa1de48fb8c4572b35b9d873bef824b7fe91fdf1969ca9638d5cba3e10933c31d4cad5cddad9699177aa357ff233ff87262093fc0466cbde7b7ec590bc2a357c403024c26eeb25e5ed6c70228347f51902ef865685e27ffc9a5c6d3fcd31fefc7ee404636eb9bebf610b9fdc347d4d53f35998d62728dd1adb4de732e30a2e1778dd1109a72eb336c9f50149f0b38541482cac14de7c8081c9ef0ffd6d656bde4a680d72ab90dae30aaee4be52d68ba0ccfbbe37260dfa871e733847fc49dfb80006c325e29ecdd4b879c6e153cdeae980c63cb3e3666d193d599aa3f8019b73eca36c5947be3a3aec018fab2b854339e66d1605b8b30cb071304d9e16120fda6365b3388cff325f55f6eb5cddf09219edf36224d9ccf03334e5adcbf7204b3d8b9b80fe70d502f3b2af7a6d3203806c2765a1b18838abf3592c628516fb8a589c157439235435d64ebee3f632ddfe3cc0391068417f0b7cffaa5573fd8ecbff1d94e77425e298a5798934cef49b03889711dfcaebb14401c47cb91ad2abd43e526a4362cc79b6f49e214e65b88e3433ab89a5c11b1a9f640526ce45ff19f488be358b0d9173f24656233dbf025fcb62acaac1c5c35a1555406f11ac1161e66128a9c0cf2f45004cc5f0384a0674fc43565976fd0a18db529926488e5d912ee52bfdbf41aac71e276a1cc967ec9fa3c8bc6387460072b60911e1ea3c92472e2a56d8c4696a980db124c65d6c7d439809a116807b9f79d965edadff2d71fe6d3448a0a7d912ce244bddd8d5d8e2891fcf5fbec651275d22c6a5ec2cc0d4b36d3b5e264b9adb446d056070d5135b75fc7fd3145c97bd4115921c75a450e249af030ad8dbc00453d14449b4a0e5d469e0ba6a35537aa02d5aaa0bf0973584b93986d08d6b87065a0c20bb1ca6fcee1652bb5a553e3b2d2e680d4dbe710e11661130c8beb5646e838af31176b6d1e3912bfd270d92e6aa0fb38aec19a6e476c66aa39f4afc6371207adbe1e1736c8269fb69f9ee9a0cccc8caf974fc240e331db1a99b8209afa5f988f4d70f8f70c60ce738daa28d311d2726b562713f411e5e65dda225b2d3becaf7eebda7a8ff3f7d3485bcbca388920b1bd60fd3b87185fbc4b87faffc07f4fe5b61aa44798e60b5b939b10172e93cb1c9e8b0cabd596826160c56074e932f407d885c25f31d9efa1ef481933461787c4bbf933cfcdfc62796d7ad3dbaa4c7cf46f34fba6b36742dc18bf8fb7de5ffbfed440178fa163e64cd9a115c88b78982a4987ae41078deb5f00ae06970d06c2a33d41c1aebfd4086d23ba87b372dbe006ead247345fa012a1778f469a6e7f00a28d783d87952d4b1c3973b8fb856576c0c269210dd85f5636691de69af5a1809d47586d5cddbeff0663fb569ea01339a2b98c4729ed9f5ddfd8b550080065a5195060ddd5d80b71af13de945a134c031901a6a1659be92c441ebad4c936883952ac3085db187628ee5bb9a5c0efaa47fdc7c4d932d1deae758119beba149960ba21774f3a054abfa8c3584c25f1aab82c4daf05ceac64364a71884e5289a1f54e207f1ae83599a65fc88bae4c1f2c03401fa29c37d558655851124201c59a229662c017c6a043f32661931c580d3579f9558753686a2e7dfd2820c6f23a2ef7871601b225b95f85e94c53cfcd05b31612869e7ffa30f2cca51fd5a25f4a8b0fdf67493bec3e29e59acb6df3bfca174b0897bff7520491155120305a6a29fb3361ded8e6e6c6af52b66f629154bc0f73871a6325f12443e2a2ffa86b472591d5aaca3d4208bfcfe003ec24af4fe4999a1fa836295a392c5a79f897cd74a3181157129d0c763dba4672e4b94aac8c80628d5ad63e55ee3984ed88768e4629a257cefaa254e699e269f5debdfff763d6041858c3a4c75118154d50a740bd806bfc62c357e55788d118bedadfd89e9cf4d69d0ba26db7e485b62a41b3932413854b7ee964dc450b3b27e2d2e0dabb5a7b6e1062040af30747e809f2f5b547d940f80a15d6a4a06a82ba1bc7d3b154108e9eba786dcafeac3bb4549bbdcba6a6079fea61ff8c648de2c7576cf3e1d4c24fcffdb088cb80ad8d5d764dcf3098756038a5d44cf4f2443b2bdf8db2f456ec5a8c22847d8b2c96370299afb3221db9b7fda73110351bb470b76e07c3583e5bf2e427c1b7022aa848ed133cd5338a3b0c61ec372c092807a46c4c49a6b40ed1cfa35e48bc3d61e40d4aea4589eb8fe1d9a35add3fc9a46277ca5bc3bb625dc2907130a1e605dd178c787b7d1ab4708325e51a9bc622c3d968821d3fb6a93bf2e27da5fc1a1c8524a5066b237fb2a8705a6840f9f5169ca37a1915c3976296057f22478aa58b266faeec5dfa7020c2345a8ae71de091648fe5f0293689cabe564df39935f861a2ed253734198ec7252e308c99aa19fbc7fa8498e5e832b9dce1af644b0fcbb51e6aa262da5400bee0dac02febef616e04a061f619fc02a7f83423e6b9d95bb9ad446d3e03aa9e132f36b974f08d568fd7dcec06bdcd3c8b26062c645bf333c612d419d7cc4eba5587b64626a58f9fe72dba16d26d4056e34167db2189df342235dbf0729f35eb8ebb372e7b642056f36480c39e8bd62232374be284812da5f56f490009acbde7ea0e12d9fa41186c6d9a84d1b3b107eec29d464d71025fd2d72485c4723b8a42accb3ff6e6f5d4a20bc115764db8756348dd087b8a04f6bc4303edfb2db4f3f52fd9fcb9dbbb00a8c6fb04ee28035da202b1079425d4156a05e516f115d34775a640b0f124854e861091dc6e23fbd9050edab8d87e60f1ffd739681a17113cfa304ae51566c7e2f0e4327d670548a4baf9073212f64fa109abd22fbd221de0888f22f6404ea779d377b64e1cc09563e7157ed75ca5513ad838efb0aa3078a9955b05c72ef8e5da54f6de35c2d61aa2a73259c2a3c00014b826a3ba60511e6d50c53d63847e3744ea334f5ac7176891aada78be22549c8bb0faaa0c56e10f02e9f5637be3f1fc429edee0a4060b5d6d361f05d090944f4c9ef00bfd404a63991232065e45ef4174f7efb3bfb566a7411f6d369bc1150f9a2d7d762bf0c192311bb938e0343d69ac76a4985da4ad9a2e7c3652acfc7f234c4556d77ded6f9b00d89599f8f748c607b7c1faa8dc08ff276665f68360edeaad525d33eb9917ec1abc90b5a7c912fa39f6476e18e019c7f7240b9faa7080421092d0f13678af24a96c6904d8d3e768425e002da8d229a1d61f9d0c2c155d4227353e67f356fe1073aef06c192724f3871bc85f3f8d48cbe9661e06e68f0c7949399daefe5b4bf8a8abb8b5b7bbc5d75278c49b5f5194d34e82d8c9e9369a743f1b9741e2cc397f45d7a353be07d244bc69f1fb24ca585323d2db8dfb7ffaee83a0e137d91a50184c1407b5581720be8e895d8b7149d2ef6cc1259bca2ed61dd931c81d2efa7e6ed8e9c0731de3d5b91e7064cb276b2eecde2dbca92ec1e0f523eb7583c9ffbf3226d1a38859776e606a0270c034a7aaba7987607a028752170434d6cfe120afe1e1a6f093cf218342d4726c80381191a395890acc09de9d6d3fd5ee108ad6c5d923fa9f13e02dc171aa6555cb414c7bcf793a9db801dd8445169c5d86a2e770bfc1ba4212a6543bc4ac43ce84751810445f46b61ca22b9b5e7ff65e589eb18975c364face2e85610b332882b3c0d573c4628ca0a08b4fecfff924bd3886c165ce595e810cb8e184ffd4d2ce1436f2d40850d786518097a8eb1228d95a9bd4ccee4fecca69b72a788518c84faee3e819e5f2883a23a098a9177f0c14931d1221fee9f7f993126ff2e22fa6ea95053b42bcda32d452e664cd2133a0c6dc3178ea222cbba6e9687f182bb151ced888ab55bc8b857a60308e15acf6f6ada4e84cd32503181b96b1f941eb51dfde946aa7930883da0f2e6fe440199c95460c396ae18ab6d8ce971abec91d68526db51102ab2f11edc0a1219a060b886b42af3d697673925d52b70b131d793b5a" - }, - { - "seed": "f882a4ad3c0b9642ba650459793cdf65252e9f6b20f2a15166b49f90760c4725", - "pub": "1b0c29c98d7a5ac1482d81da4959cd72735d7c462f4d5b33a34b84a7e55757d378b8c49114e26957c5d3a1cf6b292e89fb45bd307f17104756164500ad9f4440c6840bd0f347056102faffdb3ae01c62ab07fefa8392128197cf7c53a6faa4a2326ef554a68bb7c5b46e48957549967ac6855f716275405dd2d6b9b5e38579f2bbde79a4aaaaff4a47c30d10aff5259d9373fa044023387e389754a6d8fd07b3bbf1584a623a9f4bbdae4ef7683d828395934b6f867723a5118b37084aa59eee822d2a0a150168c7a79bf665d70ee998af722f1c5c7acd149bc866eb4723312006235e14fa3377c9859cd2bf40d58e49fb9470a74c21e139981c1edf2d4994c1f8e297867c431c016f19ed96198dfa3765b4c4fe845d3ef9092b5d2bc884159e2cbf6e228524b3c62169445901719fdd1bbb18645541a5365fb550b0e9a36c1c8f0102070a42ee3baa9e28e40d1db64d02ef534217d00b7947b43f763155b09b98df0e5e70073d839443046e8141f77c4acad78bdb543834b1972083ca568120b40ceba868ba92838c99e14a6a45e630e001dc938a46f16f98ce0bd28255d9a1711f2a60a67400ca1d8b09ca5d9730c30c62b0e93f3d46f73822de11544fa67261a1119eaf7567b2698df20037f54140e2e0c2113cc3bfe5e5a42e34ba5422f15c7c23aa9198f4639bc04dae21b3fa6ea91e1e5ee37a1d9560d1b4d2fc501b9cd52b4f73110c60ac36f6d69146cb4140dcb5cc4438aefa2a61b89ab2e6ab3af9dab2a0dc4f601c4c5ee826c0e853185c1878267e21047b4d1a89461abb4146d0d066e916ca43fd3f005f460dc6ec8f9577e2c473f91681c8f53706ba51251acdff47ba855bde6c44647f2696c4fddc1ad7ba968ef589bad3863cc244c52e699f2d308ccc64e62ff3df696a7eb88e3cda8cd3d31168352d1021f7397f6cb284e57489bd24eb0f35e416c8b0f9c30cba5c85618792bdd710f48c9cef21c15b052ff44026e9ddb837c6e7e728b6d35f8615ba0a78bfa595659df5c03e23cf7f954ab9e8c3157d5e58695eeac5751ad1468d61b6d5721ca002d42d89a0b04d56d347bc1c3626a3d50a11ed1a68cbe55994bea684e11dd2e1389c2e9f5a9e40b1a9689d381ddd717db667f08a48cf79599227fcbba1fb3e48934e78491c1e119d44b431db338aa829064ef24fe869c7b92126cd1d4e4ec9929d7b7e77ab967f96705c5e8c4e2586755ee258438586d51bbd0e9c420cef64239419fef179da6d2741838c632b3a67d9afe9ef4b1eb61e4419bcd021403a58725848b16d339641592b26cfefdf943f324d000b277a363daba843c6da15b4e25d8b8893143a0763ad52d2076baa66a9722ad942ecf76ece3ee1d4e3a7909bdee5955844db150c5059b4cf3c255187ffe2a181a16216b14db464ba15785c6d977d8384b6324f628df20da1ae285c175ee3ae5279d26e7ebfd0f47b59a8fead3af8fe73abf81cd8d8e3667ff8fa61c2591a3722279e9ca9f9c8383830d775c250cb860b334cba0b01a8468f60afc1266cded42b63ea3e0d6cc7fe44bf29fb3f316ecd682b6324fb466478e43676820adb8fa194dfa6a90de1508c5addc7d4452e3e995bc6f7cafd9227f4600496600eb0e1c6b2748daf3ceb194cacd3392e2143b550f084ae657e1d0d8e8e80ea175f0728d796620d5e92b344e9b353c1260cca3a02e58e6d4148c9f086b79eccea81021deae34e440edfcd5f40360d2609b201f4a0e0eae8db30e03d45c1cdb713a432c1e078ce0b1f56e3f6683718456d03f945a6420dce2f651e9da97ff3f5deec611f7309b380b475b33121ecb06ba091588407083e607cdf1a2e59dc8071d05dde3655cfe05cb100081278ff4924ee9ff7eb6cf4b3f3cae9e7b644698048fd06bca5935e1b504fbcfd8ffcb702986fa7a0a5937fca9281968a2edf859ff367c08a6da964ed9ba47c2add12dbda656df4ec3790cee945d8444ebdff6b039b4f6c4d7cfd8d36b9cbe15152f12cd35204f6487ece57f423fc2da2e090da7786effc8e551f4cf3d67842d17142a0720127c6c10e6f237e69024b1954277cb8d4cc61e4050aef3c01138d0950270b36cad5b938bb11ba4d573ec7ead2aa105a84e75ee8edcb319a23acaf27fae28ce458942268aa938dc430f759c02aca61029245eca51b1664f31e960ee98828caa74fbd1dc064841c40852cce1d0f72bb8261ef6d21799d7c22cdc88c68b0056ae1bff09e0de168fed79dde7867ce4a4f858392a46f2c1a3fa9a8ee1144462bdd123345817f3b16a3f239e7a7c4f839705ed9f6ed395e47c01980d491893459083ef8954530560872af5b64308c8b71536ffaee8c79e267c0c8bdc5023153adc644b8e117696bc60b9bbe649e741cae850213ed45ccfcda8d7ac345a7d877c0108ab58e2e7c31af7d650a015c02eae3d35d2d11b2e2007f24a1d97848b2565659ef5f5868721581c605be018d992ccf118e4f2e517a8ee2a1817592e00ca58fa4b267099b694632cb61677c64037d9dbf299348e7d9907729e50477be6968bc492272c30f2cc127c8d51e4e3a416b59c3a525321ca9a3a4f4193bbaea17b51099fc747b7e11444a100a0188a9011c4ed6703f7e6fff51f4772e8ce5e50dc96881b3c7eba8beaab5f44ec630c8121dfc00f12db8ff98e802be7df0dfdb51fbf5acb1a7bc4eb41f7574dcbf2ec3947571202a405b6b73d04dd3aca3bba0157512020b557f259a8cf4d7296844a403413e79f72fab2c8e592627400ec22c3226f0775ef49103ef16d934af1a1d3f005ead3bca17c91b8cd9c2a4e57bd97ce2df286788d237d85b8af8e3de5a1ba48a1594d57ba8e63b046a623e87a9052b117c99a90c0db8481130575bab6b9264e8874e57314d7aaf0d1d67c5bb6ecac1f45baf6898a94881ab44197cf3a0345b411fd68b96feba86a0beca1f3b81fda769b23513ceb48bb501ff7ea54687adaeddc5b0b9e0a3a040c45967bad34392ecb5146abf5da0951a9ac96c50708463d13ff499e064b52764348328854be135ebf1cc5cde25d8a57fe0b3be235b712d40f85121f27a61264932582dd9729b857aae1706a2919a7b2daf697bab8fb874339a9471b1a96092140926a3a8fe551b1b3817546f2e9b367c547cd2b02d97f27a1801e8c0662c5f5532537d78dd8da496888bce8c067046b4bff7495691e38fd01e1c8fc4ba0b0e38c753a0594fde9c9bba400555d22fc2f446b6a69d21951ef4dbb61f9d4a044d42613a3da807224b36bf183234a27a5765f3f602ec393509787a71f348c605990b6580caf0e96550dc5a78120438784bbedf591068a9db7a5de800051b35c17b0051615b8b366c29de57c0ca55ee4456553ba1e5cfbb40fb3070e6edfd488b4ba173b59c241d4dee3796b7c8ff052b3da3cd4fad9e57102cd742911c3fa74b90ec273e66e03128cd28746b4cada6f5dd2ffed3edee528e6d19b661505b396b9cfbbff30d22fce8c38e8bd33611419dec4175ddd6f618cf01b529a5a3a0688c366237b3de4de22ac93a0c5d28a9d1c741a26d3f05f9baecdbe736a31f2c80033f172811cbeed85bbbaf0d5d3889babf7cfa7c8fa0e31cff2a4333b07f06d51091bda5564796e081c7627cca7fa18c914a12ad5f9472114c056cbc83d9ce", - "priv": "1b0c29c98d7a5ac1482d81da4959cd72735d7c462f4d5b33a34b84a7e55757d314a0d86274d883b29c29a3f3c420cd0ad849145b72284e68d6e35e87d00e5cb87c327264e367c7f2a175da85b78c9d67f240b4fb0d9f415d69ac1fd2d2b1d0c71b7f7c119dd51053380bea2d2ae3f293b27ad5f1d52ecd8521e6a845fb2b9d842445899314298aa06c180204c322911390008188641c268863b88c4b4242992201221409992222d4067144922d11136e0987310a156094b68ccb162c91a40d21b4811c968922b151c4b40024b62124329042306842b4098240724420851420408a8290e1c665092705e492919b443123166621464c12386441162604390d2299040b400548000108035291c24519106499424082380412b38801a18c433471cb188509b784d0b82d99126449b621ca84281b972508136dd0a87058440450c8054b86209a049221326c0ab27040224923b42cd3b808800870cc98051a3368d1081213b67192146421102aa11400a4a6484b046e0c8051032608e23882889450094909042821ca2251d8168e0ba320da4449d4c42d4c2808021646621221c430649a446452a20120a50822190608c609a2b8690208669c4006c2420902266a21194a12a43001c36952b684e2826894368181160118973180b220c0308448022d20310c11350191906c64228823126d2236490ca231494625248864c4b23018b22c0a0371d4b44d1b19841a28429940280c170c189565d81481a3426dc9381062a48ccac62d4ba6694440800ac485123612a438828b4270a1446619a469444241180450d93829d218301103289a228ea11666040285248005931425a2424902178aa4206e62980d0c248d09484aa2827123b10c93426e83104cdb820922b78c4b185001070601280201074814274201044d58c82501b88d1919804a322a012840001010898049e38684d1b460014981e1447061806423a325d384610a296ce1a02091924011225182188244440224206921918424a88103961012c66941069144a43061c68de34864c440291a2291a4b060c2104a14b58c129545a0c44108b448244732ca342ad096018a94448484686038845c80301b01081b364c4c84818422821c06045b84654a0621cc224a11c80198222eda8030c1048acc861009b860198148c8a66ddb46000b36910c474d52026c2143500c4900438431e3c651541626831241a338894a444903b00583282218018d03228e41380ae2b80961044dc2386e09210d0b0820c1b069c440929a3682448600e01824db228ae334458a18405c88650b969013012d98440a14104554c43103416a9a4426d3044dd20202c4446ae4140aa1105091106050464814148d12a088dca66c43246aa4462c84464ce0b88098820020188521850c1c30512182500822261b472453c225e4c405222085e2302ad21260c13202e2162294b61024109119125113c348d4188411982509c628512484623686cbb265e292445494081833109c266d4830520938310a848514a74940428000985193148c1b9304248185029469e4424649144c13934101b65192a609c30491a1a42d094792e31006e130324c386c983464c082250ca74c1aa40481b26148189211188cd23061e2269208380a19252a80164093c669022644c0349110284e5ab22d14494c21b10192225153c271d824429c26620c308204b290198389209820d8484591341283b44ce432012302048c203199b44114034489c848c33670124050cab2491499850b871102a5889c2291182268c830114c824991428001406819a07154b82c0c35098a128599a4089c48640231244c2601dc908d1213320945628932864a8080dc822400281004c15093a04c81b06580901008b7645c2265e1164c18826ccca491ca0069cc3448c2242861a00ce3460d81322d4b4052034811e1c68500192d51948c0a854002308c5210302239010b235222038a20c808e404661c428e14c141c2a06482324d02031114a70121004a1a398863c42559188cc81282989811a1326513172604432853a081dca68904c3101a0589832208022429203262a40488da1029c1960d543205cab8111ba605e240891ca48c509601500644a1a2491b83055326211ba7901c206994122a23816118b72114c791c3342c04869153a629cb242183c85148186ac1a04901478988026d5a0866a0988cd5abedf5326848dfb28a4027d9179f2841bb34c5be63237a39257920003e20076d5199458d13ab565327d0c2fb83d37dba1b950592adde926cd886a4fba8f49d494cc131361abcc7f453d7181e69a6f587a3722c16c6f3264241125848634e6118dd695ffcc96fb434e1f8acb8cfff077ccda7a71a8c9d5688e1d16dc3e5d30b20dc2acf408d638dd925b54f9b32da50e0d874fbe3d236af818517d1e6c776501527367c84e088f74059756c9be54b151b7036212e7ca56cebcf97f755b5ef0a013cd80e62bbe48f04a297502132aa741629fd3c304013dbfcff7fde291a88a2c5c3f370ab3160a0d3c55c4367b23a7dddba0dd45460cea09e9df92552077e50c13b8d083c60b469b5343749b821c967d4a61803b9bb9c973e5f3a7513c44bd1ea93752f39a67fc5aed0c977d3d698fc025ffbb80b5a0994e31320ba9139c408660113e38840a488e16850b718d8f31644e26067a17237515936b30d7eb8ccc04050ae946aada6bac1c992e97c5f6e2f08c2ac9e6dab58a79110aa60b4b17e006fe7099931d4e0d63ae56f4e3dd607340a5f2e592bcd49c703fd002aa927681fe995cb6a534af0b7cd3cad41e9dad4a96edd0762d2311d3f826b4eb2052ad22d99ded142d7e66ac08724f4d20305b21dfb0264d44ffc14e3bdb6ef288aff4522612428681cffb198900e0aa4fa27d8a5b653555afa5ffeda0fe892a616899bb2c015d8a90334efc0ec82189eb32733121062c3b7da71eaa3863ae4fd5d8eabf2a5b77f24a8d62853dc588761be3028bb045453467a25ec63acccd3e609d847bde5b4cd129a640d2a28eead6f2a8da663b2e44786388fb78ee01a8b384bee04b31d14608fd5ed7919f1c1b6eb61ed5b45ad1d060385e784e5891a3d8c5934a012d16c0f88b18e3fcc36c80430ac03fb6db2b3c04fe541c50e7d386a772080118147d2a036108f2d4fd707aa1c7780803d9fe482087eafa1adafb3ef33c1ea9ad1956af1d99bf9d5bec31537782880b236f7b814ee52a7c771c4561f95d598f906f5197f12dac9ccffca496a9ca223b57b380ddcbf00406948fb8a06f00da5079862826b2b7555e0a96b5fdba9ceb9fb82fc28d8c8c17e8e0fdf560cf78672f62c7f908c9d988b1cff95fdc4daeb874bc72b2e6084a58d3e4a4ec1b8676f8edffe2014cef3f83eff0631e9e5d43eef992b4008e4df5ebe216df8e6f9bbe3883d85373624cfb65cbb1521e525d173955b4119121a5535e19a1f453b728ea0c1d6aa6c76ea9d1cca92a785a2f9aac4739f12354d04b5525b3859fca059f2e7274acb891cb9c05379ef8230ea579d8a3bd49e1409ac892a4b9d15b5ed7409d8c0d074a727f90a40339af17bd3b3652594afeb32ed9e2da5f27a01005bcbc09d957ba7ebcc76f4b8953957cfef38f2f4eff3f0baf44ea219341efe3183ce62ce104eb99f7517295e47728f35bfeee1586c37c24d62a2f6a73a7fbbc8b0d1bc7a6a9f6700e8d67db68a5d6bbc16b3b1b2690eddae475a2b6e94568073a8d931c329df5c81f18753756ba8a1c37aefee7a2c62701703253df7b61e8491e6a4854b903dfda5273bdae291c8e645385efe77bcb7b5dc63a46205bcc9b6d29b6d5582623d1060d26845802272d50077bfd4a2a21db973f13af5831ddd07e1b71460c55baae71c4aea9e3f03354733f905d1ee9863ce206a475a7de7a497db8363e597ebc74fcaccc37647485d354737b1fcb72305ea602932cf5691683cc5f3319f1e5db87a9607358ea6ac996ce10639e1e6e0e08892b66c10a8bddfcaaac76e2c159782198b50abe8561eddd85ddcd4427dd99fffb3377e6c85dcbe867c065e3c24b9ab96c1483f7182b41329933e83fbf456f8f31ed0e3f0349cce91919f969c0d09f3f184fc250f887f7cf2038a3c29491e2711997837e45a5380b2a0873baacfdf47a4bf36c75f1fbed93a673da20b89ee6b9cbbd6246d9c5d24fc3be39fb10744c3683731edc3a5a61e5837aba1fcbdf8c1c7831a642a1607237bf8acc9d93c84fb53bdf52cdf88964baee535c5c075147782b75b505d65f06572518e77f405e8150385e78754ac6ba13983344ab07f6431a6d97ec774af46c02712fd31b7c88a3bda15f77d6d00ade29e34465ff7c4555981f42d176df8ba4992efd2a50629ba47068aa830c473aaffdaaa5ee67ceebdcb8a67000cd711466d2c1b0b9e50de2dec6b3a339d68aa8b3ed430a843780e9639e58e22f4194384f527c9b31dbf1b29a9bdc324ead7a0119759fc09a16bd3af1f299f632827c61a43a59ca1d875eb2b1c4fa288e88c212b426b88f4086c6e77e910d13fa90a31b65121e125edc5e9cf064af262676df5d8b912831d7bcee3aa4327190909190e643195e9e912332cd5a64ca57e56a4908f727330c6fa3cd910a5d4d6475e3206cd4bee0c04e722cdd9edfffffacfea06d0bd8a246dae31fde29a3461a5c9b52bfab6a6a5744729e5949ab84268ecf7ffd9c106d0ec8ad4df93dd3688335c7c517d38fe071fe423a31b1bd6fa440e132ce8b81ea6eec17adc9f9a19abc3549755bb751ec6881417341fc8b4249b1ac145697b6744659c4d4fe78ae638c7355d6a455ccde761af3492a6ef2c12c14d41f6312797a798c31880b1e840adbf4418f7e4d645f7a967715543c87a3c011c4c5275ed934687a0b2bea90edb37ef93b0c68dc56317c6400f443eaaa1a4875289612305a0bf3298de9e6112a0d94685161434459cd3b23a68ee5c984dd1b6cc416318bcab7cd87b93e3e2a9bd492d973b1cdbca825c90f887dd468a2c3552729399be5a33065f1ec2399842133b57d154684a9d99ebb12797e8b2736c8db31d29a8dd9c2133d09e222af52c77cb45558f9cbe2dbbd47c369c4f5a108f111514b30458d06cb666e20d2261c15de37ee69e695ec6092c83152d737d71bd44ae2b291b3d82c571d665424524688e499a597e01099a839059177264e42137843f545c1677af775de89951d06251e4707a472ebc135d361f2cbe887ebc7af191326132c02ce85e50a23cbc8fcde806de7e96edea88e231a23d1b068dedffcb880e37015025fbd5b8d9d3bc2d337542ce126feed71386adb2d3921eab38686b838fe1e26d2e04b67c5c755bdd4d6da57b19a45653aec5ca217f70305d4f9e39d115f334f44bbdad1906e6426b2070054800b4b26c5e7b83a2ccb081635224f3b787c846c83572878a6a846035c08676c9655ddfd2a3a5c3e8cd50cc78c50c41472b2bc8757be01b030a49e71687980ac588cb5e342c8d1131d43ece337c4fc6868528548589312543002e57aedab6a5b20d330cca5ac0e8d7ba6bc1a53a982f0a859db0a2b1d4a7879051fb0048d769d6ca205bd3896000c9edbe462cdae1b3f12741cccfdac1fff8a8af42c966330c6b90c5aecb4e36eb520a6ef59af90201f92ef9f24edfc51451e3cd0287fffa061ab886ba36298a5c4a2dbdd0f080c8a749925381296f0aaa670e5ee56f67488bce19817421586883972f353a20b871e99f9afca68ff5f568552b808360429104184aa7ecef3f94bb7efcb9635fc7abf63a01fa4f60c7d91099c31c8af8cc26aaa68933f35fd1cca952a968a6c494eccd20b8fb6c84cda38ebeef778b6854da3e974cfe822d11d6b4c2e8a018b3bc726c5d2eb435efec4811a3baba3186728086823c1870e55c14f494399b2adbc8affe0b8d3649124620bdc8da28ec26f7d16b7ec274d0d891596b285675c6f945bc3e559a52334f371f4e7f086e72c4f3ff89629d52db982139f88ac5cb497408dfe5df4207f61806e9b7c0cbe629fb295d5b6c535154b413f7351a6ac817750303501c47ce83b45120426d2f0303b0332d3b2623d90c1beadc2476d3c6eda7bf9d6670d036a6cef7d89aa8809bfa920b35cfc36fb7fbabb30eb8dcafa30695b8ebe46c867869c96b4d912e25ca27faba6d00e077c587b495a6854b2c24f16114573607e477613eea0f2567a1af0dbd800b0090d1ad4b09fc4ec1fccf85b4aa51f871636d5d38a9771c2f3010805d097cecb436e727768c5e9028969c53516313f83263917b3dd5b21f30ec7e94d6cc1954b7917623b4a7ca00986c9079f2e4098b54ca3b5fbb19ffbe1f7c1feab132dede92923ef25d5994ac2eb47ceb35ce536582153be37d68dc60172a04b7384855f699c2200c113abdb687ecec69e6f09a43ec18f30bf4257323e40d0eb57545967b48c4208e9e6d6a091bb1e237d7be69a564779820a33489d6ed24ea6b0e6ef5460b9de9319bf94375c5bf6ab74c1088699e284a8dcf4cd1445dbef56e3c6b723daae8cf6bbe41cde5e906a4fd067e646660f622d8aecf75bb42dad9f0d9556d05801aad95ec6b1db2c14327942c08c259ef1ce308d3a2f61bf757bee34d9e53ea16a079630e405bf0c5c5e861cebd2d64115c23a6d5ceee59df6e13d270eea8526009a2df71c6524114c87c6bf980274bacff48e8c63c9eb73c102ee93b5ee19b5a3c083affcf5cc1f0a124fe6dc5b464a98833eeb67a6fe694dbc71e0879646170c0d815d03288139e6e38b1febb310ba157de6ca7c82c34bfe5ac7689dbe3ff1ce2a5fe6965cad127c777bcc132aadae6427304713f27cacbcaa094edb75004c500e1e1fc8e3997bb357a7a014e268088dda4f0aecbf48587aded7af2cd429e3196c341dc5de61b569f8b6433cda70073" - }, - { - "seed": "6f772fc20e7b8acaed601515c37671e31878842548ea93c36c3b69678f620b21", - "pub": "16968fa96ecd37e13f0e0070dfddb71e4d65ab7b98acb9dbcbe08ea188ec680d15dc14f00755df241e12afab21036f24dfe17265c8f8512526e14bdd58f348feee43d56be9a4e9da30492f9faf1497ae0a5a6768038fee4caa4fc7eeb2af4761bccafcfb774ad1cf828424a647f0c3f17e65785a4d8dc968334d2f3a97e287aea8778a7fe91bfdb2a432e7a7eb0449159d35afba0e51c458be42bf405304e8b1605cb45bc3fd84956206245b42999b8d8937b4219e747e90a12ebf99f78dd13247d7fc5bf1c1383a20b70caee4e46d21469aea88c5c33273b65b2ca510e118e4dbdd9fcda451e9d7f18bf77cea8a82145d57132de499fa17560047a994ddaf23098a2d1f41cb37e1900469ad2d1a16a0c3575e70c5d091cdc307619117a60ce06e3cc7a3964d6147005f956db2bd9ba8686c302bbb7c9ad826e60366f54da0c1a9eb418385f609856e8c3393bb86f10a880ee6594e86a35d21bda68a6b0b5cabd960c14e3f1dc5bd8e3df6e2205987ef2bb1d9a42c6bf90e0e1cbad9c05c0754d9a8cdaf3cadcca0a2838f3f76edb54d092f8d2cbfe6f3459fdaabba2422884dc3b84c4b857222c767e8f6a4e036744f1edc4048ee2155a157e9a50c3f21e7c2fd2cb2a886fff666ca89095ff3c86fa44ca45ed3bd0441f69bb8bba10505f8ae43a8a12664e6d4da4eed3f3e38b52f9884af4e208d1d78c128f6835693f7fa21131eb6b74d73329cdbc31606ceb290788c34d9e6e7ae8979fb76704107b438b955d18e054e8b1b0274f606a6ea69b3d3a68f2e4535888c546cda60dffbe05fdcf4e9515181b740cc42d659b109b0cc1daa253b04db6831a0bd2d9f1b2c202eef4cb6bb50ff99c3becf5060daefd1e72044735f4dd76d689854b503871235a86ee2db2b7eea8dbf70b858b2702e033225c91baa2f3e60e6a4a98505c9b4b56ddbfbb486f4321dee43b81881a653bce48f542cabf5fc84fcd1ae8315ed9c2acde658afba80295d492a8ba41071e549fa765072f05af543d7ceef825b7b7762accd06b37bda7acf384985f935e10811a4340b287bcfe62c4a2d9998e0468f1d32c7cfd5714c1446ba3b8d8489f91b42e1b342d895b23ce995ab9a28e2e15b4412935f5f020217bddd372962531b4104b02e30203297f9f5ed9737fa1a6b410dc3670b8e5566315db170cb78eed0a1f428c0a49e7adae3fbdc3d19ff842383609097602e1d4cf291460342030da8e557b2df44a485ace2bbfbf5e8caa96717f073f4e6aace6eafe5425d337fd8b2aba9bec7702e6a061394139a0c8c34b98207266e3e5f8e2a0b5a2176a834e82d8d8b6e627f9faeeeeef9ec3ca560782f0fa1a311f20d4fd96b6b8f332728ddd120a907fab32f4317a465c4360227a6ebbad68ab5e4ee2446e6436512ceecdbf646663059d6653ea2f5f09210e1db884ea544a53044698969d5460f08b0849f98ed8e59707eaaf1a047bf8cbdc1bfc8d937e8cc0b342b5ca1a3230ad6b543995d2ca14cfed56c80c90bb496ec8e9203fb0da6642582aa7d42f8873e45d8d8dc1623d2153199f9b00345f5e2eed0b7b94849e649571d95bc20d666bdae65ab66ef3d9d144bba38dbf4c1ae8049258cd9408e1e7766e728aacf95e012733e0127cd84895447f43d259671c7999e6f20ba4a1333015b32c0635cf8750182a4fa9226aadb55fa39eabced87dfd6e6c6e9bc71583b834f92ed88ab6a8207828da8dbd679283b5e06526a618797d6ea186b831072525849970593853fae0273c5328237e05bace6574c15c58353beaf6ad98a722fc2bcd19135e0448451d40be8d773c54ff3bb453ab7b8acc236b73d1d86d5289b4e002d8c549a22deaf2a4061402dcf2939192ee83b31c07d5fc2ec81d8945ac1d5fcfad6418bf141ab35a9c56dee9a0f61347a71e53f3a64bd658383abdb4b5e62516d656d4b36e5ba569d97f7abcc965d375c655ab6350416620c338285b214974fa68ee9c8a6395db3d10a24cfb04032177231217dc1271631c850fc17b6ae21e2ba819510c65d5fec30f1597e602a25f830ee42150781546d6fa7a537f3e310fe404a87ba58f93631a666cd1362e68edb6b7f7a1705c7eed712730f3ad4e9e7c5da474ff26fa619c0913fe250eeb93106fbbc9d4710f6f4582e7521c35877048e96cdefa76e5b3a734a5be015e08030f2cd452cf62abdc12915835b3efc52d4ecd6337f4aed3db0a3a872ba55dc8712c681c862e441c41887343eaf97640af21e7193fc7bd7e6ae96c8e045864a448e17e22695a0007a7a18ba6e84d0cd629673abbd832a968ce7940736dd14b269cd2af0188d552eb8ae4beb3baa8d291ff4729f115c92bce23b93e6b4dabd75a216eeac8da05ee415f363c68ae219c307f605386fa28b4277677c4df8889634d4b285d552a7858496099739aead29f352731ebbd5923430652182501478e3f034bdba8f68333ffe64ba4b0b11f1d5daf970b107bbd3860507c5a5f0595f3f8f9efb4d45d1ee12d0f05998a9a43a6e66f81e1a6646eedc31913fbffc4db0e1fee9a41c6936867f7e5ce6fddc89e720399a48fe4640f9b8d717939ce722e07f8038556929b16f1786a0e6109625d77cc87ff00076415f3974964c8853a4aa76ae32e88243ee46c7fb31eb415d9ec96811d644f7fedf9866e5fe8fbba4d0062116fbe2c9c94ef52872e89fce281809c5aa47fbd33369dbc240b6dafd5ca890948d8e8823624b98a92a6e99980400bff3476a58d56047424c797e39e317366222b95bec1e6b3e1a96191dede908b34cb2ada214075e2167aefc87c8c3c7d43573a29f99edc911aca92e7c873741cdedae09e51797337d368054def0755f9d7c2a4d18dc3f0e7dce6b7ffddac872139e9d5a103972dcbde4291d9fbdd85b81828c3a30c0672d313fed631b3d5a683b60ed10503953e1c79aba18263601f8d3fe78d067b83e00c463d514f3ad7ca334dae77abefd270013f63d7aeb424294ae19d173b09235e548ce5ede052ac1dd3ee1ad9910717b4ba48e9e8e784cb4940c7250945c850f2dcbc7c9721faab183c32056021ea6c095d5469f5ade557fbe60307e9714fbb61c3aae84ff33925d3dd9e715dfc4ec357d2e251fae1fe4a7614297264317ebb8d0fe5d67ef212eb0f5b2b176f58864341be667e589752368ea47ea259615b751e4d7b8d1102c07b60eb032b3bd99a8a6e9e2e97c065c4d9420e26a6e11a435cdc6572cfda6344a95632a658018fde1f695ad358bc485fd288b65e92d9c190960383ff528a8ab5242e5ea6a872a0da912bb011c7b8ff5e039389cbafbbe23afb1e5ef72b0cecc03bbeb58dbd57634f563469ed3f0b579fb6518ce8c536e23d56acb74ba732478cf8d89b6bb8011e75a8db3cbfc3f008eec5baa4c382ca94005020bc82aac151475ee0fa94430db54e17c1c7c6f77b36fa7a8bd6f788d2a1ba48fec214fca6476870cf4d8c7888a5b1a9e45a9d66b0b04ea69d6e752297134a4e1a92c149065740ee5514a2ef30cb2fd009c6ef97a6cda60bac9d0425f0bc135b1f1234d8ac5f95b00858055095db51f811224ff1e8d29a7af795f85974825f8fe3acfe8ac6ec583979c4274190114d9985286c8399e13ad93f93666660618df7a2b417008587cde5440e601b9ef49526ce3", - "priv": "16968fa96ecd37e13f0e0070dfddb71e4d65ab7b98acb9dbcbe08ea188ec680d6ca95959e5fc76fe0c0ba87da755d722888743073b81da6933a0ba655c269ee0825023b7f12adc5ae382225757e9298ed2751ada367552c7021be4892f58aa128f36a0481453910de0aa139be018c9dd379a16540645ff72389d669c1ceb2144620692d2203082a4300ca40553a0314b9029e2440c0292419338049442259a302112349219186dd1162d41046ec192049c980d814620020210040621a3881101244510c42199341189286c6016816428664036269ab84904368821c00c12374550080c89164a4b022e58284143000a588484e4b4054900818b064649486ea3b08dd29240cab804c81686d9a691241629622850518888ca104600c2001cb6050c072c20965143468a14c965dab825a1c20d89a40c93104c0cc02d24b269e3000e02c38d1246498894895a2401d1b841818265c8400800b05123280c1a976c99188148a8709ca024db8628531441129245a3b6014a486c9bb67051a2249c928904390e90002611893012304591488e002869d1b08d5cc264044688da963003c390dc94298bc091a2166413984d1c48654406895c1280a1209143482e8a244563228244b2851a40680a437122c15181a62d93a06cca986023272423a90d53320213b12902416d1107605a20060816244bc65081b89109459200c54d12886914395214358204c544120744cb9610648820493265d3c4515c184409b430d33480831021e03464e4b4801aa304dc96690337868424414a02491438081ca74419202019020c21372a64468909220993c0242200208802809c1432ccb481230189dc866c8924111a172edb302a88404d11a54821b4904bc22441102001312c41962051c461e0046a1808840309101b3262039448ca184e53c820e0224141343210413212478aa0a26cd3c66ce3a68d143066cc46621ab9088c3822ca306198400e23042e23156290a66011808c5b208ac3104e94946441c290d8045081106c4aa88c0ba96cd1186411b44164364252380acbc48c22b4810901904146069c8445083650239585c4c891db2048a2c8918a203121361214034a941470534051109690c09285c04828dc968492884804388ad1246081b86489b269da268921098d9934489ba845e00609994640630881004412e008009c22504b1071020728d2c68c8134309ca40011436c1b200c52002ed3822010382d42264cd9384280106110a4859946050cc34c0217008098912343260084319c361118b08d64402a1a04911c317000a88ca3020adaa68dd9101023a24c49144004c645cb266603b9701194009816320ba048580290d0441098428684482882b089c1c89112058504a90de0022589a63093088162c808a0a868c0c8891828641bb1081205491997900c416651164ce1041093469221012961386e04c10040a0892128500994801202019c12281907810241289806200a238544302518986d11052e0b8865094984c13249888024c4062e9a288a90444cc344010014922342120c3281e0386d81080ed3a82820812054b0840c25445bb40c49164592107251b600c496108b90655040619b120dd80026493468ca0491004791db0268031062e1846c601669143670210700e1460654a429832602d314061b29019b042218336a413209d4226cc084442449701c19695144519908019c1622988005e28631204482c04265ca4400e0c24113316ae3b800c1126a824684630685dc4801a1a824191582a1828804a1300216909322700a138c19152c44104ecc484290426c20b78402444651b20984b0649230061a0021d9c42819044a244684131206c2084424996c1121001b4249e1a00cd1288612380a8a3005148570cca22090348e903625cbb864da462912442da44670148405624202c812652418860940120cc74c524488d3164ea0062811a20cdc34054a08859a282820444219b70d0947520a440094c08d0904401442722009254238059a264cd3b691430492cb90918b320ea0484410466202b464dc126c0819899b28482415451014010cb78160304110948da2366a028108434672011600dcb844198451d0b225dac80564b06924880453b290442828c1328e11a208138291e1346c2332704cb61148046ee2408c0a0461e4b8914a48901c1591d1842004346120c0011024507ad0775795d673eb6471e7fdf2f9e1c5db0c4ac70a06c9d79a9da05e41e64008aa966d639283e8632e3b6800f6192020d5e5d29f73e676d3628d0d616332707d1d9cabb2b15198890e5e78700bbe1d624cb4e37f69cda46a4d3c048cd841929342d1958278297ce260443a6c6ec52d180ca0242f2da8c68cddfaedc2b1d58747863fca8b8ea86168502a3675714ea5edf51051ca8775a827c46f9bdda4ef2b6eb9e151111fcb56287abb35a87f919828cb1a36bb0caf92be841ef9486b6737ac700bd42c157b877eb0905187aa83d6fa1cdc4916018e626485f237e8c998f82dd2f4a60aaa5f058a68b351bebf8f99b9148d2f2b83a9c05debdc5b4871bf5b87b061bd28d3abf63a296d9f04b2b672e9187e0a61ba511380ddb376c462b2c58f2594defeffafd4fe0aa7061b3c579559731adfa6ec53ba14c0fe77c221b7943f488126ca34f366381e3f7e581718e9176590536efa6340ec618c90b424fd93f0c0417b8941c992be318ac15d0be3d5ad4aca8ef696805f77faa41f5ccd4fe94d3f5f700472c220c0f72aac1c186434138bd64b1a4186f64f8667984d992fb20bb85f117cdaf5d8a24a1665f4d34e20d1428ccd6856c06de7d738085c63dc7520c47634ac8b8595104057378179326777c503a4d2f288ecd1c55117ecd354994a7c4c44589aebe48cd71a4df3d81330963de4e4d0fe352edcc8c0883e34c9123e32c1655f2d69eabb38efc5c1fddd061efcc91c049ba22e793fb01add3b893c5c7716d55d0e6f11a8ca4780dab8b749bda3fa0f4bfe7f58b30c2c1ed3afc30096b40daf30a3ed883d42c10303b69feff2c74c95bdefc6f7e5ca84432208557473e9eb7efed97f7c14f2e5a5c3ed4b7375c848570b44816aa64c07770caead196e3b674457d8fe2631e4986321a4e38552c4bf3dea38fe5bf0a1be0b875045c5d6cf7ec151f6de8b36a6ffdf4ccc3948706269f5876a249dd8394e7ccb113dadea7c14e5de74eecaf808a98bd19c5236e8c3e6a358dd51f63d5ec85b260e13dabeeae48f8c866f91b63cd8b43ef6303fe370773a62ad5dc2ddfa02d132403d47c62ff5c702222a8583609dc348edc7757458127793a19cfe3700437f9eaca3ea2d7d32b35a28196d68c475e4f12d0eba2d351a13e68a2765f66acbc272fa8b1505ef911ee49a0201258a2b3954ee3fb535e1200af84d6e36ae0263d5348c5e7287bd55bfcfd50e5ff7a3632160eea59a07e1f62aa0bf318624a0283bbc5dcc5740b0541b09ff2320ec2af1734785c45a1a8bf1f97ff482133bc2bbc99344dfc39bf60971f0cb238a1bd31a3f4c70bb03ac9d17d7da455aa3f9067c0aaa5ff87bb35c0d873099dd9df01dc456c4b306ff98d18128a0418347c22e165ff80b57a4264f24b9a573e68a454f6b873d3433ea61120fda3e825c858744be36f437fefd68c02d4ceed45975f947642d192514be7f2dc8fdf594af1caf35607f4bc342cfde14aecd46ff189feb666b780750d091ee4d90d15a10bc424cc563d5289e3af6582b14bad2af8bcd7cb5e1a9218fbd983b5394682a7bfad708701fba5559e5602e255bb886a138955d34ffe694d19a2771f793d1705ee76126e17d04b831d70bc1752f05a65594652235327e0d34ceac8a993ebe25c59df9330d6f1c7b40a54e91f22fa9148284a28b370dc11ef1a3bffe7e1e115bd56c9a939edc0ceb757c587f57fd643852587226bcacfa49d4e06b68b53efb90d54e6d3d13bed5db86a7a133829a1d6f93e90eec399c1b12799ba4ba7a9fa30ed15639e4aa52ee91de0e19c3a814ace403234c2f652dc6ebc93e4617428182ef392f24533c9bf90a1394e323266ae09a575059101d6f9a6542c8847bd5c27697d8253a782b8ffcc5492eba3912f35650f70ce7c6e2e69460a242f64e22ad79dcd98ed899ad233ab50b68d95eaec4ea12aabcab7cd6ca888c2c4fca2fb9ec400c5a434b4ee9e22390dde050bf298ce86b3ac3792a4b83355f75fdb97e73469ef20127d1870f224187145fda6a97c933fde8c0f69d7b9b1df9458b841afc696fc84acd9bca1696b837d0ed029d885376b6a3e0d06cef1a113d00bb733068bdc287257c09fae73353b1280b64b86d169d4ec76d662cc9a0e35ccb859e9ffd79eab07bfc2413dcb4b1100a7693defa733d945e6e61bbfd67b666ad80d44a4eb8b5aa89fff62895982f3131606c4751b060177e250b67b4c575bcd35477e34a80acc7f23976c099f3f77c6e5543b139ddc775361eedb228967240e2591e74404efda4ae254cdea5f9211d24914c120b91e36b69fc19e60348fd330abc2e3d12952ffe99fdf92e86c8cf01cd5b6624797cba9bf50fc5c8eab199905f839ca538be8552a7d807a9325c6c410298016f8fe891a817359977df8666f7470f6094427e28137b2a36673e2fc91a8685f5b7f98a6c10142a2553498548a32bdf340f9cb8b4ea82a13ff6abe70a70de0a982fdd4c46fa587dd73889aafd38c5869acf5aea8c5152be4ad496c6b72b3b955ad73588131f4d214a8d339975f40ebdd0c045856d502d9a3a394b046d4e45e9bfd086e39cb6e96319652ef3791d0eb371464fa0ec177c3522270662ae53d380e0f35472adbcf53be7aaa0c151bfe9424f7cb8732011d5fb5fabc73a4748cad97a149f506a156709c7cf80f41600dd44614316cbdf3c61695a98f1c9b860c8d9ac954cce4adb6fadc92036f905d1725945b9341230cebb32587ff7ad4619c3ff35b99733bb419c97204bb8596dbc3430b4a2fd48504ae0780fcec3f9dc8a28522f5ae1da7675e8e7444dfc550de468ee033a6f582ffa8daea12e91e7fea798d797293660c04044c113647b06adf1c751ef61c7fa1a2c537d00e072964da5f7f2a2723a4303b8af0d2be943912e46040c8f51b405a8bf1e1c3efbc3430ddeaa1aa36b04d62d04682fb82585e7f2e13591bbf4a1677c6f0978729656c1ddb797803e5ef06f5a55912bb1e0ceaa67eb697555d8c30214e996b12b62de71b2895473d8541933244285f3206d92a9acef5cfa5ceab3a140530b9fbf452a4b1869c02c3c690293d8f8e9d2896c3884802d2c5eeaad1192dcde622403492359e94940e17c826a8f140aca4eef854675454381a483ba1e079702e6dfd21c377bec23c942460a33368feaf9c14b2650bd485e06fdb8f641a4b148352306a96d4ff6c72402768655f5890878dfc3cf162e09ea596a89c43283f983ce14d325b457a78cd699c620dafb8ad62f1df216d81cedad528e44508a897e5733788c8ba8cfb30b9a23858f84161579ea34a33c2a3415040d9072c02c08b9e91b594e8d465a06cfe004b7afef32a5f054c59b610a2ebaae39c0c018cdc63fa2d6a19bdd8a2936acb8865955c8a1999759c758ed0954cfdbd1b7a5c70b6d6a15acb7bc01e7a4219ce65bcc9616a0ad873fce599cd212e4c088e24e23cc3bc394501978d409b2fce5ce92ee35c0f0fb53d4fa5e987b866239877a357b5bae442652fc00866d1269644c48e481427b33a6827886b7808a55ef1da210265503cef96f04bf1659ced25a9612596222f3b31ab7751e94da7456ae6f92263fb80728fa697977768fef1f92d6b5c65af2f9f6bb320f300a4ccfd1ee9050685afe6cfec19553e6c1a2d463c984f04a9aab198c9c6fcf1ecd882edec5699ce0c3c89ab157a89a24b57e2ab6822f1b7d2e731c4ef2d5edcb14713012735d86c8cfbd0188d3c0f46faa44a209ee1c51c6fc08edaf32e38f8e1d92a821526c96d312b0348a47538daa0bd64ecff6feba76897df607df4ca33332d162cf6efedcf839009a72bebbc66982d725ccfb137e15126b8b8bb91514d3772d1d225ba7fda70f139f107b7f48664fa305027ae4120a8cc77e76cd6f803b72a9096a0c83e1741be11cd893d48dd55d08368c86197a620671a8a2884c5d7547898af711e03dafeac0470f119b312539be4457ee87d672ecaf8d23ba62883d7026db36331e27dad642951aefa30b99eddfa2e3b933316c7b7baf6c481f111e0985b26f94bc6d857856358e6ea11fbc625685033cca8e168a03b2881cc324264ff143df22dfc8cee7c9791922d870fa7c2b90f311468093afc4578d683320706bd443f0dbbbeef5465036c72f38f93e0205fb058b76527ba0558f7b853a679915d4d8f1d9a8e675cccaba0e5ae7cf8a2f43ab529ac51a2463c167a0615736750c37ebcef0b916b567bdd88f3b5b0dd9a793e9753e795dda621771baa4b9f05e31df824e6a51a2418b2aa6ba3fe0fb31f30f6d57dc6effa15a479888faaeab9fefc459fef02da6ab38c63537c0787a0ffebcb3b0300eea0802c2d82161e648fe26611ae6d98964b8336465156d8e639f84a5262f6282bd74b08c9b03fc33ed76418951a785728c557e8f145ddd98561b322d70794546d3f8a66db9051af330a7757166b99ed575890927eacf7948d970833a1c6710826ae006de7ad6994417fba9caac6e289d43ef30a0151e2d082a2bae01c6a0e5fcfe63c23ba95c845c9c0cd84c323b6bdd244e61127e809652e7e508cc22be122ac7284850955c7adebe741909759db3f9011e4de9592d17111f0392051a0c169bf04c1177c6cb72f0d3a38aa213a5cd1028c66ec789206ca670cb31659b3d37f9e1ebd85fd9c79ef5188f25d19fe377b8d87f4be01a3b6e11d2336dfbda39e197a7606e" - }, - { - "seed": "dacbf52999f050de50b08f1010d944e5880507609948656383b4c4de15c0e8eb", - "pub": "c8aee5c8fad3725161e8e6e256feac17fe11a5cabefff01028d088d4a98ff92e6587cc409cc5f732858973f02c4ccf3e3e1e9985382c2dca0726a9b74a6f0e5087c17c5c9fb74073292a3a3f11620d6fab8b5a76ddd01356a75ba6d497307ca2be2b208d44f3b21b228e5ee504011056cbde683b4c629bff7a93a77ad5908c4875d783e147e12c9600700903181a302669c375c522605f98d97cc18426637a5a77b5a00bdc457bcae00960be9e4d4599f16c3711e5d7de778ec538cb5ed5495c50063abe073b40329acef48d18a38fba668baaa9d86291b7849ae11926f9a6289890daaf1dfa2e7b4e829754cca39915968150db66b66b429cd5f787bdf2e1b536c66ee9f7e0bcc126bb7250579ad66e9ceb4aa2f40f47858181605c9d96e4134f695cccbccd985698a711c7d576c8136a0edce74df9aa2cea0c8db0b2785fdc33fbc297125d9d94c93da92002c461075d792c8ee973d11b33a3f50ce6da143580dc1be6a247339d641c2f501c344fae17ae7b060e3165585b7d68a371a6918fc3e01a9b0c9f265b754eea5c5a25b63368a8b38810567841561a3f5ec2ac2d4972736182bb4674e4f43999f772a63147763724b764e762216dda30fbaa0ff27b587feb7587d4fcc693352414dae8838b81043eb49d0b3c0111e4004e1a58249eb6bf864b2f9ed4ac7fbda050d9b3090c495fa5646acb15da358012c12efd399d0fc071dcb2651e4007bd9cef727362b963cf16e85a3ecfaf2284850eb023a352b2bf56f9840a4f2c1a7e6bbd403f4f4d651bbb7ccb484dd68403cfeea67e3aad6faeb8324c6edec9947bf988e48599b16f6bb6267291c9244feb8786ce056b925e8d9f5c18d9e3767424b7b99bd9185e4c512e3b6bc819ddbbb75ae0ae93809071d9eb8640a76ab4efe1f297abef903bddda17cfc659f8890dcd044564e11db10574b73ad4431753219c26875b649e2d612703edd624d53e7ff3b84eecadd677108d25cf5bd5a839987d83cdb1dd9fe27ea11b453ee736b1a5f7764fed870b158a10ebe119aeec44acaf8bd8a657d924e13cdd34c30d626cf7a138b78706e656b75924e0a521a1f00c728140444ce9e01f4d9b77706e36d98f09790784a45ace524c5e499cc9719948403c5441dd21387097d7bb5be74d39cf675e76307e70cf3c38d7549cbd0ed1e8b986dfb28f06fcbe9342edee569a2243d8b949d192332dfcf9af45e11c94eb765f372f306153a367a64ab90d259e1c7bc0e455778787caaa875510fc8d56560b176eb3016dbd562222d1c0e21b6bd5b5c1c5251f48c100c7993dc7caed8850cdcb9f08a90fd3a41960786bd7c6644b306c8c414703cdb45125f37217b7aff0b052b19e69000e6f666cbfda2ae2a6aa57d0660bac8d0f267090ad7f357a082174f0ce8bc1484341d960816d21df93c5aba1e69b19b70fc0e631cb1189ce8ca6e64930ab76f5dd65d34ab016f6a2980416397bd713a2b5ca8146414eea96f06902d5c36336ee39bc70a1af44bfe504c4b7bd478536d540a15d82c33e4c4019434b11618a4431808ea656cf5dc324bca3477c14e2568b09fe878b97f3f142e544467bd9354dffa42086e61e1f0ecffc31edf2fc5ae6fc0af214546823e9c547bc3c35f0042ca26142364f425a8c80a08871631b7ca4641a9bfaf400177c0c8de8e76109977b79499cef397727a6dc31e9b4980a0a359b68f4dda77eaf997254a032f7a9ebecba42478f7530cb1dff7af6a889f368baeb7d3aacc3f5489e0aa5d3c0cdd7c2dd64e907b65c5dbb80dba3fbde325a2c2eceb77d8739c75788ea82c24c393c75c0747b17edf9c9c452393da6f5e4fc33bbe147b7b263fcdc5479d814493e598825d6df498702c8c665d95c17ecbe0af8e9665abb7bf659829a5609cde7fc9b069fd2f31eb249489f87aecb4ea6168fbdd79bfe9129c377c1662f5e7e38e8e88998f1daf8beb665f3d5dfd12b0cda86b28c31bbbdb58206d8fd9816f3680c2475ad679841dcab90762a33b20c32ced81a6a8b7a3734df5a134e29a2984389f08b284aeb1017647d0da5f8a1cce84f70049311ddc92a956e189862ca83907533fabbf4c1f842dca56e9310378e1e02b9428c9f2762d4bb93d975f40bd394678b885fb8e1b24c261b5ca206b0269475f076c1ccc352dbfb7da3a8132bec78ad6d8ac7d2ef0e100de410272fa8de65f6cb0cdedfd15f538890e4816cd16240d0007c3c1cc9433a130c8b2ca2a7eefe9fc0c36755bfc9483cf8ce44d33f38e6533f4cf2d6b0ab8ca72aaf4729a47444d844f1f5779f99a5eda169bc0030d90962d891ad6e54675a9df9ba61e0bbaddba59fc64ccd7f6c3e25fe6377fe4abf2e339d4eb1766f427a524095d29e53351198321012627f27e73c4961f26d7e146c6253a2ee40918de1a1cfb185ca61bd45a62206acc1c4b9ec62082375474ef842d448deed6cfd4c1a13ee5817a3f87f33f243a290cde2fc53299b574130228d8645fb4e7cd35cceef4feb30fa5431a905d56dab4bef2a3e9c27601088287b1c7f929ab3c193fe02eeb4a13b4cb866c370b71c7199517e150c4634f42d37b70c03b7e6ed35552f928d028bfbb2722bc0e16dc455c5739c9f4620020c5217337311445a93fdcd10ad3985a32ba36c37831fca7419ff3c91c27f114b9498e40a8aa6d505d30a2344c274f55e2bdfe4a0be07cbbed2371e9ae65759617c754cb58d649b576f1b9d2428d24ec2b9d91f853b0fccfcba61c7035d60b71ef965959ec8cc185543e4828775fda945a67dc4c25612c3e44bd5f7cd85b8b82972454612067d59e90f7eb24b736720abeea57abd5ec5cbe34e1b3c62d6d945ecde6dd778b079fb5f52705e816879203b24e642e67821e00d9e95b9b0866ca0c810d6997df85119da310b146e407b31d40de0e454af7ba4a9489e02152525840fdf74f438855b2576d1a375ec529eb1fcd7c0aa961022f1d60776b35fc4505f01baeb3986da8cf9a963c14f759c77b1095f90031d93a7fa773ac3d9af524a0ad453bd14b142247cb55f00db3e169bc2d2770e2bd1e1d6a8ec4127cdd4a99e19ac922542fe120cec6635983d03b83754486f4528208f5726d29f6e8f07e08fc2e0b5578ebf921c2feea4b81709a2a9074351b6116aaf16549bf867ef79697a557bca4040c258666522de8416dc99a12ca645a9383c605f8977416a5b1617f31ae5df92b7f5fdc0c48e75a605d7183441931858bcf898617a9e5c4eae9f6bc09401dc9bf291dbc7161877eabe5454aa4fe0d16437addbf609256a381a469587e08f3269adca3780adc198fde213ace472d59511536133cbdcdc2699b58d241bdb26e35969ce8b7a13dcebe23148362bf28a3503657e3e90f559cc597862c7ab299f4bd5cda7e12fc13fd52434c9638c085f2dc903eeda293f08e8d06fdffc7ce76809f099d519c551c483f9e762e33740e1fa319f3b3182db074b33bbe044c8552cbe010a0dbfdf2b5e78eacf51d8b87b4d9af3991123c0ad699464f07eb10a794e1d2820788d6544a44070fe7683a50aceacbe392c6f587db2c20d505cd9f4dfffc606e6744e34156188fa2b82111ee49b046401b355e331ad1e3e39c31c0c8daf554cf5e4d88654df8b860d6683cf687bfaccb6629b89a277331d2b1880", - "priv": "c8aee5c8fad3725161e8e6e256feac17fe11a5cabefff01028d088d4a98ff92e573ac728b0fb0ff35281ac27a320482f16e1f9dbba2e543bac1f109e2df0b900067d12716771ca05bae02443b5e0e66c2a129b43f0d8222ef243ac66bf6f253dd4a9cbb8b27ed958e13fe3ec457b6011a7cae0e21cd5993eba1cad51c6fc142aa0268c503064d9180820b0059300850320021b984521474dc3b064e3a48ca3148a19b690d0b830a1b08812362e83884021220018c405ca464ed1c60c1092690b251200a84844802853a08dcc20468c906d02098609255221328643b28521964c1b04844c26806344602121919c200cc8166ad916860ac685044062a3020e814421a40431a3924c63c268143904a4c4910aa801a204829a86641c82319b982598324954a28c80402e10822d51862d092440e0126601498521c584c216451390698314284946400b278a00a269cca8309a1091989641d386301997251c194423060a219348139708e10645cb06498a2291da242c01912d58384e61b449219950103341cb329151400ddb28468a9288e320200328614c884cc40808020225e2c621a2a488d14220d9a82c190846e4046a4106244ba049c1c60c13346513b88560c480c30001c4348a6082685ac849442471cc346ad1824108378de04030e13269a01248884071e1a800242071138628038390d3b6901831808bc28059b20024005020c44d6206250ac8658a4686ca08888a362e1c1205a0b041441409402042e420050cc92cc8344413148692180c1a006153040a42c281c3b660101002a146884212440419266230102148701b208184a44912964c18b3298b062680208a8102061ba621c3284cc3327080340dd9848498484d5906715c968582268e00026e4c308a04406914308ea226521a2901d2484201c2040296402013711b430ed0a409484281da3090e194681a4710c292281c14886132450b910188904591445121274204a62c22a41108460944a405918064228170641088514832a49861d42408194481d9340d1ab271c21885103388942602a1b88840288ae0202299346412482e42c4909a164ed40429dba66d5c0866104706110948c1188820220e22048a092249931620d2986d80428524198604400503472c02a42c04a68198468419b56d8bb08483a629084370d2220c42b4049920090180891918421b9105a2b43199a071d2000dc2183204c0052304524aa00563200c44b02d044151140924d1c22d14062ca1180c90106e51a48903894814b765149865d0402a08c1049a4012db3845213611da204ac822685b0861523686a2440a23318d02448260080a5226258214091000221b414a92a049d3088561c68800066c989270228261e0c08960968919802c1a462c0bb251888620d20042d8b65010295091a84903b9851c88890ac2301414454b102e49868801042611a14d0b274521936493220a423009041032a232920b18701c263113c4812316095ac26d8424290221241c9611db2882c92052c3362214c08d8b9664429801c32228c2881103038453325199384d888408529420e1a251a0c420c412255912614bb2056212444a402c481260a1904123818ddac42549248809494edbb62002c9900ac204d044710482095802661cb489202351d004919b964de23486189221984600c0b465c046219c88000425128b46302286701c186661906552964518b885a208120917669a220ec3c6606188418a386d5408116328319914658ab46449942023124a0b440452a081828600221770a1a004c926620bb46ca3b66903914111106dc4c0510a9644e2b601a2128c14090dc33669d0a670588690d346491c368a1215428bc629d39830140824e002081bc740c344061800904182059cc241dc080814c49152248c0a218194946599300e84200421154651b610ccc61184802d22b54c40462402384551286208b425d32672c3140a60a0611196845a06010989511a250d88b4810c29459ba265842804808008a3248408a11189302190c020d944651c339021458e12212901290222279010272821221150b44cd3c089d02049c4104643a071503840104708c02240144328a4c68004320a5ac02d60260214c51020076241483224a604a19870c0a84091b2681a26419c4830e41229c4c6809942529a3446082202d330090a3924180944a2264c19166dd3914c05c3027c8caadf2071bcad01c0fa81d92419a4578e1f366c4a0b298e221d66746913a652e93862f08764c91c87eb25c916155ba23f25e9c908cf676e5ab2ee562823f324138cda15b29a4b40436da7f5482881f566e3cfdd5cc9033a5c9f4650ea04938c55a1199ca4d1bf5ccc929f1b257e81406807fc490ebb50b04a72b137971c778a8a461cdb81c07e987fa966828f3c89748088812c31312338ca10962287727579315c43798bb3aadfef9b4ef590c5d1d3d3c132a9b361a48b0dac573b200519c96fc0d40162605739e4fbc4c65cac12597168c8535f6581ab278648a0eeb38de4060d32c76b1ad6b0ec0098969965257b0d55fc830f6e4d3f112b3e85a6d20e345c00cb0b85b0690973e36990a1fdd59ec99cd496db41c442b76cf0714a57bd94e446595d614ce4302138092301903a469c47fc61e61dc39a9f0f0fde61e3a1911ff12917dfbff144fbf14935ef55eab102eac5ebabd4f0a018a693d55aa6252aee949a9eb9a7de04af7d416f490dac0c8b9a411862d39faeead3f883b2549aad38f7a076984bcaa7b9a6b12ac1aa4d18c780f454da3fd4e2f03ccd420f8721b9adbbd715dcc655f7f2970518bf69c827227fb05572942377d2c32a7d9a562c42034eb26b34fb3b6b8dd4cd5c0d5ab5f306503f27a65655e5d2af88e4ba8d7f20f6a1fe484c6126df816deb7318e9a30ffadbd34544fc6c9dc1559f59a8c46d75f6c66b7e704985f2ff0e9860db6bac6cbecbd3f1d691a9f232ea03ee8fd3766ae8390e4e6393070f93193c75e167e9301d4196d2a5911b73fa9dbf5ccf483e2ecac753f30ce69ef7592fb9cc2aa0d97ea26085b87971095b1e06a45d985ad6ab39f4258d82f26acafbb9b8e5c0d3ef5a505c71e0dd8549f7945d8f29477dd9a6dd83c03f1ccebc0ecd0c5621247fa3c841978e325ca2725b09cb01d16097e22e5ea83530fa1515d011b8f99388c844a4d78b8072d0449e3d6d4f2c279270d1acd0c4747b406edcf6ff4a76fa650c59abebce8a5d7fe67e4b8d64d682b1ae6cb9a268119fd49c08fbe33d066e87bd344e374946b11a6ae3de8323a0274e2319cb118d536957f189919f9d032337ee59781f8496be1f005379d401ec740f85cc863a353dfee5cc434db8000edc318412774fcd1808ce7ca47e2ffccb42a3fdc9734620d860b750782049ccf2683ff1a2c62d92fc18988decdb84c660bd4ce49cf660a6046b426ae68c80a359657b5bb9834260e6edd2290fc7a4734f60ed638cd924d30bd214f939f1932c77e7d221ba44185b400bac97e8e98df2c39e479233e83a403c9978e33732bfb393fd90d0b16055d23da5544359cc1f4411c6d09c2e7ef68a5752a1d79019e405b610750d74d1cb9e6a267d0812082ab2dff8da031f4963da33c7ebc42c3419f82d85edd467474ac6bcf7154056fff9bed45a242714cf8a6230cfbcb1327f0856ec5fc2a42f769414a09ce9afc05a333b7892214888646370478e73aa07b1a8a44294009ee4d1341ce1ebb15e5ff0c86e41aa7dc80ef398e4120a12c8229965e8e0f2ab0d0b8bb9904ab30cbaacc23ecc500e82af464c4cf97f9538484aeb8a475dda9d2dfff45c8adc87f5355af80111be2d0dc4aa7e2028f5631ee1297a0218cda762e406889f4ac9fdb954df766ea99e87ec77abf1ee720971933094af39cc302dae56f963397b8c0a41bc500f966597bd69964f64c9cfb8d4780c1b008176d7be7698bef7779a36dd5dfee116cb0aabb90cb8664e7c1d0ede2b2f93549fed9d58d83d9ad58e40d8f9928de16d47f830fa8c117add35b2b041dbe1b0f1ccdf4e7a352ff5d956d908025ea1ff812660a9033b99593cb02b3ff14ff9de0b8693ab7aaff62fe2b0d7204e06e97446ef9bf08fe2c0d107e18119204860c3de428b28ae7988d3337584e2b6db56f9b0d6885e8cc5767a1d4f47fcbbeacd8c9681ecab56e72a4156283d994a00a9f6c19875a2dbd31d9c2d9a9a09b48e16e02716823ec37a473787c41203886eced7970845e8aa9f8abc61a053e02459de3d15ff5aa41df156c656165b6963bef5ceab7e63cd40e5b201ae6463401c2fd0a76422740ee1b74be61b3bbcea29ac4a9faad527ef4177b3f247253343258ecdcea61e9bd42df0b89d8a58b63a8950b3e11e9417949e5d3792ce0b55b5ec22408383f2a43821ab623735f9d86200db9b24d3addf1465436c571d391320adc06a5c7922d9ff14109aed1a9f5d868ba9ebd1ae72e10d71954e3a38ee5e46ec154ddcaa98753dc4f467ef22b44ed3e5be736d95a5160f96f6b07913afb9aee9dfab2c4e36e9d683efff414610c66a09ce3a4fec74d79503613d438848d5f90ff7a89874e64acc80c7f7ec943b25ffc7e0f991553c33736f4d287b9877dae971d06f5cf6af014783f39bf4568b94527b3f4033675d8cda7fa94451c4a16c199ede9e8ecc10623629b990ad68bb58a93f42025b5827e6b89a6afaa3946becd7c8fc38005668de384ce0d434f688be5bd57d98e681e62ab2729aa0e7d3586621b983db87eaf79ed8ec3b5ca72e9cb3b1280ae4c808e93974f80d97fa16f4754da72553559f58b122dea98700f5627cebd358b6e98a4a4db0d3d44c90eda3d1b96203bbe540e45636b0cde64e141e242cf120db87a135dcf4988580f2d4917e6b33beb1d37a4240e837924ad52439748c3b2945c787c2b88779933d1e64c8af859cf2383142cf7e636d6f9b3bb7f66fdcfbee3533344fd55f8d715d1f54093411b6820bb1ecd877573078d6bbcd8cca1e1a7522a40bd7615e217bf69fcafaf887dfe804c3a42a5f35720e9d36d56cd9cf00d599090f2f4c4af1db46294e1136a1fb950fc6034a1af7689f156ba184a2a046f0315768f44babfb3b0ea3d7c53436fa68c3127f3e267a3cb345323c1e5bca6e99bfc53910fbfab41fa545d9ed54e013d11d662c06169f5ae5cabab0503dbe3341623976919e7f6145672e19e839a2c864d0c33b6f6d6424a5c4207529962ec4398a99cf8f62769f752412316a4cbf10d36c66c361530818f4edaa1b254ae47fed728d07da64c52068545e920b8fab5ac22f5cb7fe4b64689c63e026ffb55c5b7d7e58392a52cad3d0c99ec69d7694cf16f85d3ff19ace012abcd2fb28f8f822acbd6d62a5f20d003adf0dc64587788d39e0b382c91d9d6b41a4518273e11052a57f9cf0b0f70c9a6928c7fe460c0a61eb59c191dcc30259fe8a1fa9458ab0e66c348baaa60cb42aca3840ce6f0a325bfa03ca4a536c0ed1bc6a70b2b4208ab9fa093e258dcefb52d345824625e8dd4b439c3312c02c6b43f6af2b0ebe40e2f493856fdb8978d5df58d413067de3b969dc4b24cd767ccbf79a22ea4dce88b80d2b41b273ddf2c47fbdfacb20db1c13ca42f4e7bf870dcd2cfa612fbea2d9fc93fcc7238b63d76a9a03b6e1ca6c28cb217ef179c62e3dd160aecca4c5f84a33366bef3b89336364e96ef5125e4a7f40f77086f5bfaafee3502ea962f7c2e0d2b6647b222be838a1b581bf4bb655ec7ed4a07163bb7bb5f8d82451471ec3f8208706baa9a570908fca5dd830c14da682b5d2ad844142a43717a2c8de922b71b34813a1ca920562e13a6f79ec2468ff8de842183c49911e645413f8316727a657208677b9b02b01910db2c287ce02c7d4ceab16f1054e13361bdb50b40d8be992953d3ae6fc225087e33d02c5de9f6a8be3865b825d2b8f5667c0f12ba6073dc5dfe9a1519bb66e47732a83bf3721a29dbe98483f55860b9f117a9ec69a4eb4eca96e67256e0fba9b27b91fb8cc92afbc7e6c3d2225b580ff8ab0c201f2817c6055d126e35610d4a0a758496c649a59c6f5d0ee4aa4b17611f4be381ac21ab28e356e319a5a117a7f3676450dcb3335fc031dc04bc21001c3d50dc2de5db5fd09457fef9ee0f0f6b08e9982bb54708fbe88e8c1bcd87d240fcf19767af30e07f9824c4437424aa22b7a8b72a0dcb8aa51707bdd07d88cdba59499c05996025b2cabfaff6270b97846a779fea8feeceea1bafe66e7bc4fe2829d22c48f79db581856daa3197407e87ff6149e2eaf25acc557a451e70ed1bd5e5bca089b7db744b8247e7863d809cea8e1d93373e5d3cd07e45a583891315e6dab66d2c79312aadb1c73b4c9318c43935dde59ad20c708eca5a2e71cf6a53cb214aaca746fe3988e08aebaf592d8c03f52e739576f7deb757c65ee95d851c0716a2d69ab220695105e73c7d05ad64d9f4ae0d15b5f8e1aa0f3c7b316463cbdefbca7a111c6677a73a79049683ad830558ca2f8697d35131f61a26fd9ebe439a25cab859b6236410f476f3917f524d761bce93b9bc0c3f84fad75d39be3955fcd756a127967b3aed97c3fbb1e3cecc7ad3454d75132cf83e86d3fc04839808cb39d8e562e571c40537731dac9126d8308ee4db0ec92a3af35fa4e251343d63ab0fae97c61ae6168f00e6e693d30418a391ab684a956010f20e18ac25febf10192a6cabf66d8dea658ae9c1cd10dd1f7e654a9e532566679801ec05ba092711ccd5e585aad85308086c5407d81080798bb5c66c3fd3153c9da022e5378948ed5abafb5990cb49297e7b6c5a4fadb76421b6aba38af317d70e7fe60ab06eb48cab69e84e9b435a692f3863568508cb9410929dbe473a898665dda0e7d79e84c622d19389f14f2149b4c4a84fe6b09e5" - }, - { - "seed": "dce29422a082ef073fc92c7f7d718f556439b278f15734e4c12cbb3bbac25637", - "pub": "1c059ff250cdd340502885e324bc0a0660ef3452e5c7f5787a02aeff9f201489fa3e10e999f8909663d302f2facbbb0c79822dc748e7508ffc44886d6c244deea71bcaa2875f7a38067203a4439e4a36145a083f0afb6d234d40a5a82e1f903bbfb92cd2715205fa2b8346fe8a46e62bcfd445dc9ad6c1d3d126507b8be9cd578965bc733ae2f9937ee38831fefc906778b628de393a127fd77e868c48ea7df6dc98716b99034f62607cca19dd2b62d7d3472235650f0990c1dc9e8aab7b6f9c32c36ed273aeabf418d1ba0454c1fc7d3c4c5e66bc806155ea56dfe14bf091e46b71e96388cc9920d1c75e29ccb99da11b4722d81385d3eaa090b3461e995ac507e2a22a17dd6ddf325a81c692457fd5b7b8dab88187f11d546ec7f705c741e34bd03b65f476169ab8eb41c262f8432f7686ed1a7c57e17475b02c6bbdc5873730f9eda7d1207d6cd06f7f0e16d71f0042b44acdcb8fa4c1df7719baaa9d38ac56c7d432e54c6648cd2ad9e3e8fb36ae61fdb7db5624df679d856f1a0a5dd8a099546db118e2594142320174478861d694d49df6c15426bdf82f42254f3bb61efbca898126b314022e1788ecb00a3063eae50690b51e3ba5c25e17254c67719b79e4334d54d7ccc455e27d9bd75d3c8684b74066ff673a295415cfe0d0dca341522119ff985de90ff9c5f2f042710533ecfc9292c21d4b3b968ae7cf11a7a6d3a60f0f72a581e3666261bf5a67cfde9138ec806737c2d6cd6a61a1d503cb4b3e6ce93ba5dfeaa57f49dc9c54bbb983c631f101e1d553be100af8af4c7ef7b3e67208a08bf1d9efed7f506e4ef5b5340e46fca49eb7ac2ee291b0575c36f898c4471e642ccc5ce9924b28105dd7003be51efc3b13735c5aa91916b3335505172665003939c7e14227ae4a358a832fbccf89774897227d06bb51c9ded711c152b28d6af99127263e44520be88c6054f8a64e296538bc793a6dd6a9e7d379162e2de7050960c4fd124c57871f303fc3b271ea8c05e195a48ce1b958d5b48d63fc90200640f5dc0e216d66eab1ef4f691853ecef9b46068190f76a0d7224c4d514025648b104f789d79827e7bd39332c8143978511ec92164b20f389b411fe98b500849317fcf3be4df83143af6bc3e26a56eeb1817b571300b6316ea9aae181ef0ec8b0385e8e95b527478fa98b961b40c289462e8f2c9b0f4275e107a0eeb628e1c889533fc3667c7e11e8a45f5c0cc8bde7cd520f1230052154292b25976e5dca72a5723c9099602292e003bddd5618aa6bbd8807823e5934f38fff48a7f5143595ca9771efa74c617d3da1a694317fd4e8b5135296e1ba0860955783df64df89d11b0c7691f9eb7eb7894521f37022ba7b14f188d3fd898cf701751ea173b9dbfb19820551e86d9e9a3a0b34371961be6627e58463160c136176cd8cdb244f37e05862ede464c329927d187f5588d72cfeaa0bbb301892e31810f7c0eded0e48a5a7c4c65e95ef456cec0e239dc621b318c43898d529ca9ed1cf9bafeda84be53113dd6f512ef25264b5574f542b6517288b5a80999025bafd64e43a5fa12c88875cb7f16dd4fc43cb14e94c231cb16a5c6bd26b85b1f8d9567cf9f2f371e135c12b5dbf2f93c0edb69d0dc476c467db1f0c56ae4456d6ad09275aae2d2caa28738f982618cdef4208ff55660023c8ccb5c4574ba453c8b32f16306cdb6bc414a986c8c9d3d0cd4f968816f5e3e610a48e39e84bfea742d03bd20c2b9306bb9a6598fc1f9f889e9a3704ec7754194ba158b97e9d52e2421a75983277ee4851da892a94729f23fa538c50a367830fd98645762c2be3472ede6642efffdd7f517793268ec609fdb3c9279fbb97a3eaaa906242dbfc8e40b908c3fbefa4c2dda3eaf2fd5fc72ca92ce0ef1c13854e2682210308e44f2a8b60a3a1d0e5ce6d444f07300e433fe34af7e33db9886635564bb0342802c0b065ee56e6ae6bb4e7626dc7a1987a6ed2eecb5c04a6e88047cbeea46689036add81d893f8f8653a0b80aaa1a0f830972a46d352771c2a4d8819a65f50c709579d0ce89e93e2764c67bd0b8cf9608b8bcf903514233d89bb255b4b81abed52f1a43da91848e5cc6e5fe1094d324d3aa2e8b59a4e7115b14fdc17305fc974254e616716b0007c99e5548e95fa7a9c8bffac2ec37ddb730284e3704ea7b70f16e111f4455b092086e644b06cbf8a0f60ab94a6d86bf35168522e7903a168d715b770a156ab3581911893c781f0b5ba08caf818e1eb334dc8112b7e2513a5a88776ab40cde42f10908e22aaafb9447f3e9b49c149008acfbc43b2a0f3996d6c7d3671cec13518c1bd3c250160ccd6a090bc28dcd0bcd99bed948de23816f32042a81628814b3b2cc6d2d75f6e7cf739ff4ad69d99aed4074e62f409be71441f95d473eecc28e47eee36d57dfa6acc4fdfec4d2d165e05a2b50adeec9311dc5025ebe9166d2cfa8b6b2661121206901254e3c2107662ca379c10c0901537f39b06a88a276eda9f5996a895070cce202d91e725daf39477cb0d305f2d28a7191524188d6c7497e4a6c8465e4f4f133435aba09d57a2e528e40cc3776160c8852771a2a917bf38edc4bd50acaf3d0481924abf6c98f843207561c3cc68947e575fde36767e24427ece694338397c4220c8222e369c71d8d0bd55f2844518e2e5e65da1fd75371ccb0b47eba6db25abfcdfabea0dee5459cfd21b3478c35cdc77cf9d4052273337f6ca634e199de5eb32629282360eb47151e428a543c809f9e38e0681a6c2d25a5fdebd943db932a219e6a5565b8686221db5fee651410ca550ef51772b3c53438ba1eb45d3a74ea7ef80dc3c1b9eef775eb27c73892e28979a9a2c19698948fc04508ab3c27fb294c1b29ecfad4c5fb1aadfe4f46af0005fcabc245dc2ef7168e039db33f4b7347743bc4fb434e2581c1ba04b3a13ca0e3f92a06f71013bb5da372bab177a6c38cfc3c794a15f79a44b70add834c1f425f0fc6a526efc5c5be6c0494d0aec681cd1912047fd0121cacdc7a6679c61be4ada5f9d1d11103746756381d899900c139a41308e5452685404751092042b0b963e42a7a4c647328b2bd7fbb5b361f893ea514347691b57b2fa88c66dc80d779e2052edf476a8dc52c328cf526fa124a6f6a5f028355b1375439829b5184f38baad3dfb4868261281ccb28d89f7858f2691fff36289deeb882c6fdc298fec1729d04d37883d84535976a6d78a03492d5e5a6671c3d0264c383ff60bedfec30828f32fcb29b1e572cbfb4eb5e1ea6f1a32ee1aea16c3060f026d4776311dd21679cd0b224f9a8437167b77375ba8f59db3a653af28516442c53a58edc985bfe906bf0d9e134117f31641ef7fc66a7f1edc1217b8540737676e3f9481c8a54f432a5ca2e1e96454bbd65a861f670e18853ecd580431f98466696cd6588a5cc67e2a1b49107aa349de0bf5909ac75d74b91b8b3498c94f66fc245485fabd68592c9fb51ef135990931bba7d7c211f96a4fb8b972faf7aa1b06301e4cd44b08c7950f2e9ab1a01e8d3f64ebbc1f0da4e4acfa9ab65c9fd9fdec9d5b44e634ffdba8b2e3c054249dc311067cf8f967ced627e9bc593953a07a7f807564df945e6176419438374a92d1b50b332e1ba68de455f92a", - "priv": "1c059ff250cdd340502885e324bc0a0660ef3452e5c7f5787a02aeff9f201489491f39ed390d725bf88e4d0f7ca928bd149aab54f90e7489749fe284b7b6adb780787d2ddeb2813ac9c3b1531c22258839cc2a2f1654a8409772b44de0312890cd1813cdd7d7fab28e6abf57c9b63f99463e4716dc70c29d8baa12fa4bdad83f9410091a070294262e2202254a046200a18cd4902d024552ca907102306d48984554124422b48c40280c13479014178204b40d48c281234690183172a3b2901bc95123114c4992050338301a99840b4629099810194862a2026201813040b40902484ccc94309cb451da24000b90881480280c2384c4828c1b0629023026d426490c0862ca2886d142101b0451e2c06d194260d9020dcac25120c9902193040907928b3828c98065d944288184012141689a164a641224e1348d81444cc2488c13c38d8132082413711840029ab22c511264633205138229e2a06c0b334e42444a001431592611da1686e2b22c8a428d99169254300e1330221a09280ca72561180992046504106a8c807043a0815c46461c876488c24c41484580b89001c440e0066ed0068ddb0442cc282012b7701243650a0112928825e32841511004d23046114504c94492c380491b382524b60c1a122c6010929b082eda2841e2204684a84492b28598a410c2a2699026254b9429d0846c5388895b8868d49669630860d086842440410b1142d322001483114a18001437104c845022a030e24490a4180ddc128dd89868d8a481544048d39621ccb0400a9911d9a48c88b65019177222382952424ec0c8848a34924c320540320109b10414272c53363088102599482a18b880184801d29011482832a404694434608a468140802d81300a114960612481d2387008a86158a620e2084681c6808282059240090303915b2491c0c29008b9315a446a23c91084b0850b96811c812102348ca4820422a66d0b463208398ee434901a2672c02684e1268d83a080a42826c4267043006004302088262e89b46840249260c08981044c82a82de12671989285634425c3a08d421651d82226522265d1980c0c484553306aa0a409183928644670e3c26dd4408e84468698065222278ee21442080880531860539009c11481209188c4c07110a8811118300cc5310a210e04982c5ac0691b01914b844013926c52a801dcc464e2828408b32053864151802111260c039331c00684e234060a938d60b22d02c0908b0244c2026ec38860e390405a827118c025cc482a530685d4a069d34430d224048ac890c8280acca24c14c12508464a1284612331320c158510010489b06558944d0b973018c92d62b2719b9468d3c45112424622228953b62cdb408c9b848cdba86108b1705ba48959b2258cb8881921229026300cc14c24168963448653b608a02072e48010443290da446153b66880180114930d02406411c06c48488451164523b99051b80510b90d9ca221e1a484010892242592a4104849122099920c10336ea0865120c4204b308211908c01907181c46411065081a06484307203298ad10211da04514c224c0a0762e3004e448090042112214304534644e11801c2308e4c348180382c5b2069ca06452299218a9041131571da28911b414019270980c648c0b20059024509188c02443122988408a1080aa9710cc0111a018d5892515b22724aa24d0ca08d2110426224909bb65119b1658aa4850a4041cc0022c82206031000139288e2341092448941861000b1101a2000d4a26113a761e038048b422504156684b26950100ad0b06813c48914380862a24d01c24d49248a1830245196290247708082481a0181c312208c380114069150a66d0cc12001081191465224892d22a668081045e31629819460c0c6058bb864a04250a21000d2264e608890800405c3b4455cc028d92092a4a850e19841c9260a99b6411a42280bc061200841dc1442ca364208a22821c86c14446442420818265240044e00414254c66912918881023183468224a830c1106e84942959c4241bc2901c37525b426559b66cc096500c356852342e24a64d14141101310cc0906c54222988b64c51084801c42814138c19c96902c3296084680a2820a4a84c11262d01b044e0b6698a262cd83086119320c41222db084682246509895088388654388111840013190d98880d149091893bbec4eca27227003e07f886213b05013d8be5b3dd5f0992e1591e98b6920d4dc4869ca0450d342a8ea53a02af18b98677a332f4c0b8502e4193c3de9bdeb8e0ff354339cfb81910e0950408ace6e2f74ce90e8455150b5c58262e9ef5f932f2b2002aa468eab3a8d93ea0f4ad8199beb15cac9a83e9a74141e0c02d0d557d5fc49417101316a080fce60aa51c868b84446ab3194f6921dbb0b686b177a859bed08aa34df7d1bbd3c58d83635eb7a25e420dde300f41b58d5ad31e7b23e38536d0e27db2874a6294743686a50569ce6756a62e7fd8eef3b34c62cf54d7d3bc7273c01f0ed316ee268da37fcc738e522ea5c3a3bccbd881c1a90e73a5642de7dce4f5d86ac6302defd99e5cb8b69bc61ca063d6e1089d0c9ea9e6e9ffd4a4ee01e45d1e1ed7ba16319dab7598164a6170acac5bd94745e15dc6ffdd05b277586e232e5974b826af68c5fb313246ed40b91bfe45f763e42db116864364474d84b414a72c41d97b026fbc61da5b702bb44c16d5495588363c732a0e60f8b11c0a9ffaef2e46379a07644c988ac8927fe8165234f5d2fd235f8ad142f3ffd1c928202896b8598b3b6422d506351b9f80f6fb45a9ea02caac08b6f9faf8d05ab953f44a41258298ada81f25d85589fd0e997b9e577f9c3f816d9171a212496cf39577f3276073b360c35349b1f7a1f3a90b0494a31342e6df936ceff18f62ddf09de0a095bea326803c6e93eaa34ae9f941e49c7379fa692a4ddfc914ef829a05348e0e8405dc82392a4007f797db88c1d7ba6c6e53be832071a3966b029ba1d7503cc5c8cb08cb502b78abbd2fbbf344c5f645fb4196229b1403f1b5718875e7bb82e0cc9937d514f8fe07b109e1355432302fd9f9a8e609420c1a8063865a6cf87d42ee3e12085f84567ec600cef3df3c0e53a2db05c294f87502a42a803d64db0f9f1bb4d6d56de020d225889031343f353610daf39b7bd11161c7e35e1febae0fe4f4cef1f62939d3a8773ace9eefb3b8083a38e9b821377190a3171306eb6375ea339ba9638330f4715a2556536e09f8f226351d7cbf9e1e05f038660a69f83e48c504de07a9f01b0d269d41ae3bdccb8db359e60d92d829233ce98236e1bfcd7764a2f40383d9f0d17b5cb44e25e590fec5da0c3109850252a1b1819b103b1b96cd6bb5e4c85142a412ed6755cc2c4beede913ddf162b9eaa8429e488c2e9308440d1fcd488eb9f1068be20a60c0d240a7863ab58b759f53839dddb70fb76bee6809c65e98391f76de21edbfe03c135b6cfde1f7daf6d66c59dc851822b6e5282ab78dcf7f1b9c1053f0e0fc138e2f7998fa648b3149226e5ba94aeb0d749f75eb1052fda846cb59142db9c4711dfe62a46ff8d7c285dcac3d08cfda1a3a2b89148b87c17a53851062db07a716da940106fb5e398f1faa4f225db8d83ecb4d66939a43f13956d12270900aa850ce1a34054d57ef6e6ddc3d5003acb4ef52986d9858d3c9fa7adfa7bdab66773b27d243b8afd50b3513a3e8f466c0b8a5c25f40f66d1d0c8de5f131c021ed5dfb9c6a9a457978cd26e7df9b1fd761e692820726408a530ee6eea64ff04461cce6cdd6c3643acee21d406a0ea763674865a74789051a2fb535c911556dbfa1136a81979ce3d068a89843ef3d63295d17c7172dc3abd8987f745556192cc0b335814f67c1df5fbc842b57305981041d44187e9234f4819801f74a18f74f648e7de50e95d08fbdb01c1a376413141e4b6f6bb5e49600561993c910b151b0af0f801827d34872de6865d47a30915dd1c9a7ad4f31a193fb7ae0f880f963da18d3a1d0b77876b7a55cfe596356901aa5bc2d40fb046bbd5f4f382843cedf43d4c68db14962febf13eed19c41e423728d05768e0a64c7dffb28e1ac2da367419dcfbe914b676bb885b44815f50ecdcf088861dada2dbfc49eb4222a70db2c519fca6828eb06ee0beaebc782c00f431a7305868fdb2f63706b786f575edc95f9819145aac4946a07d6a8e89bf086d14bc20304d5981ddb4795c1165fc3a4681639897af596a2547ff785a13779dc05fc85c4770442d8330aa3975da7ce4aae6fa2f64c86c5d8b27fd24558aa7ec9da9a234f57dc6addf2eafc2674b38193ad10afa0dc99131984e653aae4c0ad6fb8900e2dc0cf5104ad515e877083b508e204a550fc1e19837396fee4e88830becef17c9eb3ed891a1932f743a2e9d58f2603472874ccaae411eb9814a828e1f8b578ea49b1a27a95037acfa7b7b8632aa781db204a581906d5dea12d86fe8c5e24b1b6230afe531c7f1c5f53d33c8ec7248a7787a919dfc1c4b77538ff88e0f03997d40d9b3b196257a440fb36796eac5b51d02a563a5384efeb4a2e83cdb9be3f70bdd6e473e4b5d46228767f8b1c5d2976fe10b774346679ed1dbe16678b94d8844ff56130ae64ca6246360653ad18eb838d115ae209878f69f4dce489b22702fb78ae5a92a5dbfcc92465d7277f761ef9cc11b49035dbc1a69654a8ffd60463bb869d976f29327d154e60f172511dc5e62728149bc976b42313a5ba0af95bde5616e9f2ce0b3932479926d95f243ae971128419c406cbd180b80607d7539ad9f65d76c2ec2e0eebfc159a83c25089113b12716ec9f86670f1b7bb9749720baa7b3104481c9b8aed47b23b0810f0f7b26f6217af97fe7081d5251923b12faee3534e133db8ecb61ade5f4c269288f73ef463d2d6d755a2cfdb52cbd64d36ca86044aca96abe85bf6dff510d55125fbd72acb37dd6e59b9679a3c1baf303e57836ac43892587e5e5ac8b83617ce3fa55acfa5d5350c1ac79ecaec022a5dc3931fe3dc048079e454238df3f441a9583efae6a1676345d144c624d1c9248a4bb6895d0fce53292595d75cdaa804c25808e78a617889432d71bcc02548da21fbe951eb39a76df98661488da65c4c47249dec2e850e0a643903e56a4754b9c34eb8f0da19815bfe88d1fda7601520d3ab203acc9a46a384df014c49124caaa6afd2387154058bdb623c36f5b338d94255fa2cf08f4d6792c0d1c6fbbbefe4c09a26f00cbc3ace7d859467f2f0fc04ebfe91d62d857b3b4df8b925e9c2db6bd576b07946c63f709b501906ba2835e8dc28b40acd4a2df89e4e5e746778e7901394fd9dcbb7306ba869eadf059634e074899d25287778de03774455b0a5b5f363d9819526c730cecffe67ca92d5d90e9da5373bccaf65e14ed4fa418ffae8352e0cfd378e5f6716de934f54e715ff15481d99fb39a25ec3d3ca838196b1294d37fd786cd3702171423a87ac7c4db467dc3a0e2d771fce711611ac7b105e196190f315a7c866d6d4403b493cb21d6114a8c396dc14af0b1b27b0b78a43c5652dce3ba5fa907b54ca7feef877b29b805c47f0fbf117deb9915308da28c60444af5c1b3c2a14985047c990535bb282d900583fd7783041c8cfaf50f23ded4254b2a324452253956990058e61bb2c2fe35e135ef0cbac9736715e01f46ec9b9dc7a31fe4b4fbc88efc6aabf7ee4ecfbfafb8dfb4376eed952b8038551f8a15d91924156c5b1fb20bdb288d4ea1b5c09ca65cf92bc92968d234d55d1c608dacf616e03018b51baa5a730ea0737282b9c616d20374fed2b7eb702b900617100d9c83e6a802c050afb4568daaa013b9327192b4aa3e9daf144154ab95c2c1c7f0e80fc9803860e27ffe46d1763eef5bec0b98a45c5d51283483220c9d64a8dfbc891f41845a70ff7f24febcda713b381b898f06f1b3e931049432af22026a54b0d4f55a2448e95e4a18a3b2f6e8b37c3deb1c382532421171d837592e5460bfc714daa5598a2c649478f81b3e0ae1cb83d322c5b076651d41a3d9c581ac66a7e242ac87f3a0159a29f98963ddb0b8ebca2ac771ebee39cb8ac498fd41b0b7ba19fdf23e121b621048bea00fdd49dc13226a6a6aaebea5a4ec673299f4b72a54eb25b368320b99c2c60abb79c01fda768868ba58024f25b208d243e7c43b43ae05359f9b819b676f7f8a9fbf79cd7268080c992fbb824ab22ed9144a1619843fa6c8159c9f4b2025484274580a40456a73cb6f1af97e601155f9918a3cbf9b510300bdae0a69d98db91dc4807de81f161551b7cc7be5363d79062d97fbb7b52660de1570664ce36f94e307836a2d54cb0cb0e6e317e560919fd379668168a018d00948f8c6d291266b2238a2872b960a944ce946699f37df4f061b8d8383e2840a836c8610f5ee65a438522ec8cf339fcc151c806e35100e7f68e39035be9f90025796324ef95c03aaade0bfe6a5a15d5289d96fdd3563ed8cfe95d47e30ab9f873bf39b7fea795fcfc382dc19714951ca0da85858193a59140fac1e33abfe108e4675532de1a4908f1744c9cee4c398d10b2f3cc7573f42b26a7576b7b3bf0862a3820afc3f439e04fc6e4ce6a2e492372f088a8c6d19bbe511ddc4e16fc0a7ba36cb88e689538c658373396a5e6dccca019158259993ffe82e74d9fb5abf28bfdee8b57ea62b3fe7c87334aaeaaa2172e92feb551b39c1a5e662893c6dfecf64d236e92ffc49896e5d4818ced4bda439f4b6987331e584cb60d7d9f002493fac69af9700cf03925379478f9773de505f7c7f4cd7bf4e401ca6bb6b71d9734d4a3212f234b08c1d2f4a7042b0b7d3c5df215469fd42484fecf9e230ce09656c6b90fdb89f0b8a2e3100930a6995" - }, - { - "seed": "86e9d2934bb1f65d5713e9adba861052a25c9a972019c2507a92177960294284", - "pub": "224077f17ef15a25dbe8379420d3b568500daded7cd99a1e246105850f79357343ec5735bbb40b5ffcd5e0d58d3107d53104084d80c46218633fa7442dc03d3fd1f9ec316bc3c0acab0af0ba400419a2fd3817ee6d870d8f8a5024d2c80bab88e4762c03a5b4827983ba436edd9fd77fc838a405b777d17790e48e1c2a24d9b8a13570e17d5c6914ed33c9b491d652d3b1e3f8a8c38e2b19dd0f104d0cc39c92bb6aa15e5629764accb2173ff3a696efc0891668da1c4a34258d14b1867094c7a32b52b2133bac2004e5600d4bf0f0d98d5774a689a99751f1b3e5f3822d77f483791d1f8c56cbbe77ad812c6b62ad9d09082b2146f5ab2794a18c5fbaf910ea54667f2411191dccc1bda7931329a60afd2e170d55b874062fe48baa707db40c581404003b0c389b9402570818c6fd1c3d186ddccbe5fc00b2daaf1f64ba8b6d8730f12a6b1bc20a042ec33ea23f7a057f0e1cd6af20a16419995431a2af96eee1b974509f7c61da9ffa8b5566db2d00bbeb75365937df468cbca8a562e2d00ffd8544537f3d86db54e56bdc1df0cd2d02da69c5368663b6e2e50e3a1c0a15a161ecf7781f135b437298a493c62573ec51018a04809975f406a36bc0bcb6ee32e2707a0d4115f90c3470978358a2bbe093f4de4e65398012d78c009a16f2bfae17f4ef0d92c002d0bff12b6fbc0e0c67065a48e9096594b2d7c5415048e7e202f0b8297e0ec7d953e3c9077747cf5042c9b3360e4ea6d3573e706fce8328a77e878bd42c35f1459347f24f8e5a94df51d978f7edc3b82c69cb9d4525649df3c7f4fb4108b11955c228c6037aefff73eb8391449bbca89bae7fc2cb584edc7fa6eba3f225633dcb62cac71146dbf10ae489719978984cba247f7fa054da42cd46152a36434c04a1df0135e06bd9d4240085798a51faa7d4b1377ad8b179a2bc11c83679669b1283a5a50f046518e5377ee16b948273d32e0238bc8c9a1ac2521e5e1d1b942938009dfa71179cd9fc075b78e8212fd145e7795eedab86fbcd8e69b7cdcba320da0bf65a5ba3986c91258a2b4bfa78159b212fc3992909f76e2374b9cf4e3a9d716108c2173bad8c0e2aafe3cb10ee66bec9335b1e8c1b18489ecf119cdf3d6700df2ca74086be43e90f0afa8e595969d483aac28e389dac527e1134f253e3bdbdbe96f48e40ff69887a01f903d96d10bc70904929dd9e10f38b04c5aa20a273453b11f09a61be0be6d72055db9777e9d778b2e1ee2f8fe14621cecedaa463f40b61939e1920f685e1c8925eab41bc75b99c9ed3cba0767f71bc350da868cc1b26fdfc38e1b664b353f8cb776569d6078a9b07d241d18b094553c90775fbb1535d6efe078063194ce11adb4b5ca4a5ed0e6f60fd7cd25b7f3d73f9bbcfe31d0c2a4fb90abbc867e6b7c9b16fd91054f64859662f7fd9605960799da998edcdf820e4e96745a85d390f09f3875b15983ced3ebac5b5515eface7bb64b540f9a83adcb7859c4769012749a1293d99dfdcbadf9dfa1491bda13e0528b5bfed6010ea0b6a5ac74d8290047f22eaa5e8ceafe267e298341ef1ec4bc293193291ba830b4896efc0f67083015fe827325032403ea8af17accb41876458a6f06484a062deedfb6ba96f7a3ebba155396237c8577bd5a52919b98d7aba6aa5d44ee1db495aa4d2b8744f7365d0d0cce4afd0cd26cc04eac686651f6fcf126cf36396ccf569c9ea4dd3c2d913afa7e0805e55e7642471f39bef30b115c1d8dde3d2374d32d4af20944fd432a3a6bf13a1aacc8733dd046247747febe463744ab59f6079a8e34b7a5d07d3f9ad6003929b8fe21d465688b434b85c917d4e99417e37cf375642800c599a932ab6fc02b501ef6416a1f1bd9be2a12583eac08b7fbe519d16e327bae39991bab31c45cd5eb1eb6c74ca825172b3005ec78c86ee0d93ef620a6df287673a44821df34058b8b2f6d21a2d371a5fa0caa94c062bbe7181155ccec11aafb68d96d00213b152c39079fa170012b365bd8769686f588eeeae2aa49f7a8ba83049c9b4e30b3343a533e3f56c6dc3d3bba2c7acdfcc11064b8363d90a3cb656fa9a45ed24e239a5f4e9a0d828c85f40dc57f63fb5abd5e9196e9b8efc20bc46457b84e32bbf127602d26a91cb77689b3bfea198ec9bfbea066ac86c854b4cadef40c5dcd07ea817a51089d4ef2d919cef499236f2120503bc4992be15fe409e40abdc41704e625d269e873384b869d80199d402cc3e749d48cb49d288a588bfa69675c5387a1d3c01a0f9ecabbd4a541ffa9e129c40e21cf1431140776eb72b2951dcff9506daec233ad6b640802a3ff1d75e5e1a091e59a3aa3ace2922b5efa2c22e0c6fde94fe0699937ca3695c712804e072e88ceadc0d7f92e0b37417d1b02a7d432f09bb383d23917a4700d933401d6c3ce5600dd82c4bb56f20a01675ddd7a09234c26e7cb0cf5a26a60d23d050d502e8d57601c96402d84dcaacb14756c670a9dc853321d4259ae1d7b0928575efa14dcbd6098c0db1e9b05e366b2616bf0a7902544209fe71c93bf767dbea643d97d1721e44a7af936771a943938469faeaccf22db23f0988c88a43270d1761a8b4193e70bfe28b782338a25af6fbf3b13d601d38c97b7c1286e720354e866e17fc2cbe0c597ee081b3c444b48680ae0df4e063b7d0376c3711088b82b45c21d0fa8fdd4d21e277048c11f3354a851823b930a20e4ee96dd36e36ba40db9383241eef072a329d54a30ba1c63933c26460d9e913959fc1941209c3f0e3adec037e69ab59b2cc300c6fb66563a12144dc501dca2ec6f750fd35c4612b883dca9e7dc8a4b111637927991eaab3d70cdf8e393ba8de8263d64f012a6f31da5392199948db438d2481b26a368ca0fac99aab6de4e8f4e707b20f6514d03dc4ed16841a4b9bedf8485a93951a8ef8a01ac21d90230e9e7493f61cb26837fc57db407672e4f824c92aa0b18fc813ce41679122e3bd19f9eb565dde1239b935f16c0667fabdce45bad3c3256506c690f3210de37a9db1004875e24517479252a759634162fad6dcdf26c8e58dacf6cc026a8b5773a437e341d128f0bb5a72cbf0e06ae140ac872ba8059e0d325f3237a7e175abc6a5f359ee4bddc73b63d15dc7160a97dcdad5a53be36b9bc1224253d0a3ccaf453fb0fb57259cae9ec8fefe5a7f71a23dac203f36478c13edb382aed2501767fb082b02228aea7a57cac951a32628f8f5da21ee569369809ddd5746fd969d48a46994b429baf25c29ae50f938669c835a33208429c1a1f9af9fca4a4efb2c0fa832d11517194bc0cdd211b4233f1638f3f136069bf6b53ca6a5a6ec358a59d36b371c6952da122c1b7478795d080e07f58f38476a79a647ef222ba5299716a825b70efa742fad1e0babd4a1d310c0e1411b3593db54fd3b4eb8e6a3c8bc3ac00223338b7cac6b10462edab5c682779f486a9e43fcdf43ba0668cc0a4dff98a99dc85ba4892c22f06435860d58ebb1757f1da1dd4268afc0d54faeb7ce101c0691746a366f763ecb25cb8d51e4949a20b15da2c4671713c1e95af03094da6b3806de0a9ca3dee83d4930aa35b9f4c70a451c2a2a8c130835af9078f1aa52202f70199553c4fde4613f7c4fc49a7a0493024cd4e6bd4f7c6d9", - "priv": "224077f17ef15a25dbe8379420d3b568500daded7cd99a1e246105850f7935733abc36f414e5eb6969c8c2835aa29c216f9dad0b6334e62262a86b285c0ee29772fd053f2e37b358565efa20de64960398b1630d0bc2b61ba5270b69c755fda5d1f7e04c6eda04f593e0cfebe6216c887b878df4a6585ca70dc90e419c918a4212268658420860368e88a410c448409832920a012a1102221a38260909655144484c482480442c01842462060800812d0a926084484a9b9844988488c8a08124200013480811b65161365223958c894064c30692543662a4a851d02264e424609a4040c1902dc9a80518b7719b2426e2c00593422ae2b28988b4658c2690db186a4a1688c2248e4c040d1b160292b67180c83022035160422e91a6701a84098a023224050eda380698c46982445002334cd2082d9826400a13121994001932661122010c15711816100ba569230860c9243113052009469242348419488604c300a110055aa82884a6214242000a07884bb68542348214368e9c308911458c62b26951168800b28504086408152299462444483003470a494410d416725c362a48466118886823b42822a90541280293822c439825c036108c402dc2104860c2108404428a4645cb824013b88d08c32d5b806881368e00352cc34625e1c02000908103b544c3240023130e0ba72c12962043904c0a89490cc30cd8404ee2a031e4225141140164c430a114400ca9892432216134050a49840c2812810002cc8211131064c13451431020ca2665db00810ca47013b30104906514a00524085058b66161384ad32642ca2620004251234110e2289258c050184006e1022299488d01056dc1002613966502c43094427114480ac9800c08450981b28c0c32850bc02921305164266414022a138889a1844599264541189010150524435100c62ccc34020c335299148581382459920d033530120264232232a016041a1642e0c22dc8a061d8466d18a26008274e64080c1b10319b9004e2a68c13c465a1b22449268d192250d3c8704810299100318144414b94506442261923315806905422490998458336926308226446404a169053064cdb808494304d19c8415b36009a888093900418a611019829d8b03124855011468622082810061040c60852280c4114405aa604e1c084c3328819336e09470109c6001948459c3010124481e4226a12c6902134464b1244e4446e43382158b04dd880644c12864a367241420d99b2218ab00459440020059220b800cb40680bc1848a240aca043092888451862d42c028603889222528a03685a3a411c2c80002480422c90951362682164a1011919ca205d9c04c51a220488431521492184842014064214492023766cab0059196110294041c2381d8c03150346e51c44111b98592004d43b46d0b199213114c5cb2304aa801a3863103c991a2364c482220214680238430e434040b082a91c40922490e0c30461c4462e0885111b77082842dcb848ce1b49112918d5b002421216d12b2094a260149b02451a824a4180ce0a68d5a068e0a452ca48884634841c39001d2084a5248015c028d8c4201c8a8610a08404c846020b221a38604c424101a162cd14681c30409e2c260ca842550480e230846d2802884944922053063082911223180128a1aa768c430809cb83023c4894b806054268a8206261a47811238281b1240d22631e0b48562141110418c01214c434289144740c9c288ca4610cca45003244d231621db12219880900a456990360dc24231d8a02c04270e5340651a3724129184c02202db204ec8186859266d003262c8004010b66809c4249c40680c830803296a190526cb4431e4c82c52286d530484d488285b282210a271528251411091c1140d92b6308a866888a22451485258300122079183c6015bb2810b99101b02701c341101156e63220ca4189241a0890205306406648030304108294a4441502852cc326dda04210a096a8a460cc2b6414c10020139494ac660a3b68563040e13978582924d2082498bb0419932894a424521826082486200236823136160386112482e49a2052137905438441428500ac06824c72543807050a67000c288c21052da128460164a020568e0328e63c64d8c360a04098cc1b8011c3201c30612da3869930449500820a4262801c4494336844336854340809a220e5e490604ca97cd2e2e2bc26c9e8884892e770df12063d2ca665b692f6b10744177795d113b843e3d70be0f65dd9af4700c1e5ce6814284bede6b11eca86c496d4783c70a116e147a90bf43063f943b91b2da0aefa7d216f56a70bca9bc8e673c938348ce239ad83d5978c274421346f59a6a13928fdbd7acdf5a9f3f5c7b46e2f688c9370e16f4b49156dcdb958fa7152ca1cb1e4410dc15740da3b1cd52dc96a13c04af99d300c57821a82d5cc5714e6880c671feb79f7969b7a9ef5f7492a279af0ea601b8a13ddecde613ebbce197c588f1da332ab3ba3a52034767756258ac43bb4bd82f91bd4afda9d0b31ca9742967560f63246a2528ce8ac2f7867ab6cc48e94938dd118d387dc4f363941841288dfc8e6cfe23b6d57ecd9db2e735be70d59f8316fa1ff7092d822c1380712a1cb980d48e48f5cbf82f487ed9d769d74a6866d3af531c5845e88f1de804e3fcb30b9c99c460d1180c6ade0df174e9c399bff92883685f7dd4cfc1101c5f3246f037f18479c726c2e39ee09c7773d35931c3b2dc8b7ed0b95eb473e9c21d33d335e037997f99d697e540864b7a37920603943e3fad2a43d1e28b522ead37898b81df9b11cf235a0d2f6ce95ab081b4f52c89cc564d2c986284ad824f0444f1d4f32d6cbabf6df4e7e71afcbd8bef5dd8f22c7065666b5c57ba1e00a480ce524c2b682b85462437ca5a558294818455fa809a340d76013762c19d434e509f9738f5dbf8974a32b4dc5ea47d6eb34ec18f99325fa18b0dd1c0c9f9ed94e05156e005936fdbfd5a0e0cf8c45f427b5750ff269e96b9f75d09b8317e3fbc65a80f592e2dc02dc908650f3351d5f0094d6aa809c6a12c831b698e2c4af7dd136f97a7db46ccafc09ea6f32427b285be1d6a62dd9b4d14e4d658bdb6b7354e9cd1cf929b2e7f0e54ac660bdf38b2132b73da5e8949f8398566e8261a4f530be17b5557b26d62cc9627015ce510a4ccf8b1383fe942c09a6038937dbb0455d43ace9aef51406995012bfa332511345858e74992bd776059eb83d14402875c93fe21a0a7a6c2ed741026610beb70f7aa47a7f224e2b06870fc2db38bb81f861e145760587368f87ce46c76a56f279fd6e7ebba69a741da1047c34b59a1014210358ed9f4b6521bd4d091a0952262e9266e429e93767922ad827c0a22d009ff2c2d5d17ab24060d3f95f6f9a6cba7b17997708247e0d1f15328a9e41b642a3bac0e0991de6442802baae970d827100e4660b0cb4581ae12801d5d02803ac11bae7faf48443e0422dad99af2ecaea0b3b3d521850a859ba48f78397bfd52f8d9c8f222ec7d165c7319a58b58368599455afba0819e1a9bf9cf13d8bdb73ecba315df2166c0c6ffa9e689089c130874ba13c03f728000cc83d4010a305e9ef7d21f7c52a7089ad01005746514373071484b35654ceb6085a7b26124552d151bff66b99e137302c7241278ca98edee16c297c2db128918489b948ad4da68d00713be26106f746f98887d49f3c28dcaf130673abcba13107b4ba0395120edd1fc48302dd04683f578b69e5dd70ff3032bf8fb9596b95df672cc1379a6802eb1d5a24b4b3ddc2994ed06883f5222cf0e95ec9143828f6a7e4bb2a4cae75c9dd53fd02dfede7eac8de7d1cca7a2134d285c81ca874b3ffe3a417ada2098562acb156256ca25febf4a99437ab2284ece5b6530739893b302db794ad8ce1dd1505065c4850d81dcffd88d8fb150268c49e06bbfd5140cb03ff27bc28ae066c9b71ca444f53abb596258d05b13d6b4281020ec5491b1155c2df7b3486fc63341b1cc511a713d85674d58cd2696724548f9f6c34ff467acf84a77d95ad9dece7940bdb5859e38f5fa9ae58df07313fb7efea2a5831d2e860bfa0ff56d3c58a6703a4bbfbcaed29fd65334a94ca5892373ae7f2246dffc22e0c026f78647f2060e389611ede34fb36f2e4e0e0c12ce9d52c4ab03409f0330ef839241ffc86e8d4a3c48013d25c563455aed676064abaa95aeca2bdb9ca976386eb1c93a501f49e8b96c0b145096049e3bd9bc75f0465ce947cca1a4144357741fbf716f6ebbaf6cd647e37cabab2d53f20001e54dc88422404cc04f030e645009fae8dd78dc73cc7c9527b7e0e2fb51ce9dffca0103fd9bd63e660766355d13405199d247d9c1a0b43bd849e48ed021843010d79a803c64b86905942ba6efe65c693c7e0c44deaf2727b28ca5757b0283f42f9e9881064bac60c628e2ef42448f50178a06ab2b3611aae3eb73d746a56f7a4870e59bd5da0d4228d2f2357b9d11f04bcbd7c8771e0b70b2735352f12010af4c1aff422eb6bc9ee9968c663872d01847075032aaea2b134d5eb5a01f6169baeb5f6cd9b663f31e656b29ebc3ebb4d4e502ee922031709f936a5461143da7b8d7265996c789841cd7b835221cd1432b9b5ad4a8de1d7b91fde2819dfaa75b30a5397262154bb109885b1ae4457dc0d3cfbfb63eb1f920e2b22abf02ec3d14267b8f66f3aab1f27bf27063204d64c92944872e9bb6c1e5de216a805efa1ada6029f864b05abba3964456bad7dfdc38adb58251d3ba87aa40c64284236269f1b4f7bb6fde50b5b1a09ab4fd65dba049b8997229ef62adcf9ece4ac86cf9b59ea173916e2f24d078704374de8786f44c5db7deff73c855923f0856d7034248de41e3f15d7579dbad853a8e3aa88511d5d3c234886e9a03efdf39f696240131b303b5dbca91c7e190a8e9f8b31ffd3232d035d1a1b129668ab96738a8370a9fb24347f22f82f6b664820499905ee4aefd1e4957ce3dbc2f7b975f361f26875eab1551bc44df69f9c7e6af44e56bcfe89f7b1714413affa89fb877fecc39c83b4350f931fb04456ce659f627fd9b0fb402930374719995433cf7c4e3d68a9d0fb0bcd24aa63dc213d010d37337e7012346ec3183a66c6dc76ee37a436f7866babcbde20265dcb12576323ab6bfd9bfecdefd43d0723de5215cde6340cc27c04a5c7618c84a941a6fd16b08d8346e838d974c99e432380faa5225f7786077e4d8b5377b24db5e917b1ef6a98a2281b2112ce96ec7048e531c2b56f8e65d2edac88da0b301a4961583a13ddd2112707c914079cd25c30db04e501b73e69f3806fb18605b32f35beff30c3c3df3ec77c9935a8133d75ffdcf5d87032a8b94c96871d4bd39d28f60bacf09d0a3c4ce2463ab27993a89844c4cfcb401f94d455bf91b4d2942e551ba6d960774c64541e565a2b97a8017404d996ba2b45367ddae48ec121ac7d41d5c56115864e27dcea3d211bf62036c7cf5cd6c6b8cda63dafd957962cec79798585d492b3f19bbbae1a66da41d7adf1fdb968be4cb157432d0545279b35d11bb08076ae9a84419874496d8144f9b16f669f041edc3283ef9976ba1d326fe81cd2d1d08e5ca516692a63b6201c9b7b1b078275891854eeea81d9f3839804f0429067a0878dc4068eeacfd734c2c6ae75ba147df8bd4dd3571192687626f4b1e386e955ab113335fe9d252e274320cd4540e7708ed2588ea67179c60034f27105f1beb4908380b1bbda368009a298a876cc95e6b8ea34757bb834f4374b66bc7c56aebbe99baf2332178dde953dbecd0e1ac6c975337be3765bf246d2afe2f81bdb1203ba62854ca65da641a9cac4aab643c6af824f23fbc5461e130d3fc997d1118ae6b71909d58314fc6afca92fcaa61001e8650372c8dbec6e246910a3c4a97e6b6a6cee22605284316bb2a102bd9d2485af18203bf0946ef7b18c1143cd8f705814d06284097c75a08bac54f97bf1ff63a67979af8f49f53a1c53291b5af2c94374d696db0842f2281c3c3728c652e74c501d69a756b462cde4dfd5facdcaa8100d02f4c8bd7039d3588e0a168f6d7f12fedc6fd7359ba11a67083fecefe31f808fa181da1a7c95e7601df536d7e0b6f60cd0e27c397823c3e473d1d1541faabc2a98a6761891f41e4640a88856e0ceff451545e6c6a5a09919262e9e093159edd164d905fc802d3453c33e56d94879e20250c6a7737f8582ba769eec3eb20d7e69f4b259d5d2d0e6e035c70cf26a91bf07cc937f3d839b28a7913b425ef6aadc3153cfed0eceea5e16356316f33549589c94d7b0126f00c309b46c8512efc0e65fa4ea5025484878cdb58fd172d7ca09156da41362f7d29c2216679b4044737c69e954edbe4144c5cf41400dea6dd7079e5e61fa527b23ee0ae96cda2e1fab88ae57d0374ba8c11fe6b061f3a013e5d861eee21493b87a9a2ca45231b815bee4d093d5171f21ed334d05a820a9db1e7f17f35747c2c86c79bf25e39d6eecc7ec75b0ec58b43b3ba0c56b834873f27c9643243597f39e00436bc076333c42684db6d4ae6f4e9c4589b53e95093e358d80cd7088862b594d8c52aabc2e86b89593568ed94d14d75f5b4c381a7c2ddc03b254924687579f739901262cd17aabd2463b6ccd4dc38e1ce3092068bc59041f307d16abb43fb53e676a73faf31e4013779ef8a8ca5bae57930310588f832f76acae43d405cf5359a7f81ee365f41811a839035c3ac84d96302cebf354179955da3ce5c66b71be5492c1190f93dfcb4f3e23773588560737daf7e14f7c945309791b5e9ccb582601b1874a8dd3ee3a9c99ae7037d2b25bfaab3332ed05ba8886a5938a9b8b3788cc2ca6c6b7764ab6dc0dc2dbb46ab0356c414f4ef" - }, - { - "seed": "04ded13f523800949a62580256bb20c0880663348e1aa38ef6763104dc717644", - "pub": "0bd3670f57e582eadeecaece38e27f54b2695eab4f89bda9a4db0545ab94dbf3ff8e416d227a202fa3a5a372d10f2145571e87e9db044085d3572f6ba2489c9e92e6fbbb93157d3fc7b5c629fa1086fdd33b5a96aefd8796c0d00eb81716f536b7447c1ecc18ca85b2594086f107be5478070cc95554cd2245cba13baf5b78a34bc8cd8b30bb5b320ae6f73efd82ebf141065db0b7661b424cc8ff33da037b9c5fac0e581967e9cde5ed13cda55c2c1fbc95d92723ee410c8bb32c3ff19bb2617406f04524efdbfdd5b36e2dda639d9f1bdbb9eb75cba778cd20d6c2a1350c36225bb86ff8820a742f709be436124c21e38e7b116a91d94409561ca78c23f802ceb4c854bbf7b01bd458a20d5cef22a826573c6b5097833ea7bf29fc1820becde9b11c91a19cb0b425f7c6b302a030e992b75a39f9ce7d634578751bb9b8793def70d2005a8f515d393617cadd6b86d1b405cc00cb8064d12e2c2b1aacb95644d6bc96ac37125faeaa3a173ea45ca9dfe9be152d126ba58a052b82bbc4571fa446271515f28468f18eefbd26d76178f3bedf1bcb4f0e4654572bfbcbdaa0343e8d7c95c60a5262ded91bcd10d8ba8634c1c94c634b65ce7056baa21db113ec485e55ab6c8965eeec343efe1cff719d731c81282bf805f071afdbf60f6cbe5df28ccecda4a37ee8d6e01781cc439f1dba3e66f8c3160cb09319d2c94c58ebddbb201a820a2aa2c1997f36218c09e3dfc6f358a5483695c2ff75216509fe6ffe8d1f9a530b55debb6bbbe2dcfcb82e3abd80d632fb916e0194b7d7e9d2917be2725070f35d4544c3eba279ffd439ff32b8b3b4f4c28d25ba79f83fd265659579390d3b784ff2ccd05ed88005f0b2d4e9fe33c36a76db0d044f9684b12a1772476c624da6023822a61aa9afbc9245a97e3e638cd17ebaa64e9b7f5cfed014c821019d385354b080fb046457ed45f391c29ab9f2f6783d65fea873d0089161bc23f8f8fe6e686bf319e368b18934345c5c3a316eb91aab5afb65d30b846de408e93c73af687f2276caffe114a9ac6101617b81ffaeb2f7d1710859f14d14c0e90fe36bad118a7e70ec0721a4025ce7a1e65f82111398f2e532f1ad5c14bca5487dc45d334de0f206e91a4130ee96eda1668334ae9fe8fd7b0d07c08366bf61e07b5b0f10632920d4c7c8561009bb0cda75b3c4e95b19cc609cf560bd6fd036fbc80d50eecd1dd144a9326fb4c219033b10d8647d4718e28c3915dd30487d02d6c74940e3ac666f92d9b5d7dbca179ffba57e4a92c6078940660f3a91a8fb9d4a1684630e044c54d51c6a387fc8b4f972f8089f725e3a5e7e7f3dbb382ffd90d53ce84084a830c84745ebbd7333465f01ed7272983c12539463426f590bf00fcf5697f2b60dab42e865cba298ea7b4aedac87954fa4c15b0bab5234bfed63df30ed915e26730afa9597b2644a534178a8c7b7a8a4531c9ef5df17de08874534fdbc1edba8ff14d14c69d98616c4aba0f7cd9aa57b1910243fc5f6eec58fe176c25fac1a5e983a5cbcd9b1e74b938cc739cbd7983ba1fa2d149fcdb9e120cb9cca766944b72c56eafc7e838ef92fe175a4ebbc751fb574f4f53ea8d19dfcbc089a0edff6f7a5e0d246f8b65219015e89f4e9cfb5fe5954004e1cb7dc4d7ff5fa59963bf4eb85a23c6f5723514e76b74a2945cdef8150788d68e74b2966b3c9f8c75a7159cf6911544495acfbaf9971621bc7c3d2e3332cd409f5def25b534599c6ad165af07b15d25ab591dfcb54ba288d33ec7e52af368222cbd0337989dad4d349e313be8e29833c85841255f72229adcc29a5eecf494733d25a7f2e54d087b3896eb4e21894d9a53aeefc56eea86bfc23a4d7c494df215b0dc3d3e3bac5c635d416e91fe040f4272b7b9856f93667c7be5cb3596054ab2bc6087fd5ee877424ddff1f96d873951a486c0c77f0f4041728514c9eb6dc856a82f8b13e32ccccb50c9cab4d9c13f74a65e072128a3d11d41b8e4d10200eca061fad66f80a1ec314815c979ab8a30dfd48b1e99494e91d8ceec3f3a6bdb2610715f0d0206d67180670b7f7def7767b5f5a5d8e360f5e1da5f764c3c30f03c699f1d867af13756f82a575f12f4b5e7f4b055077ac8cbcf7017ea108777a3bada0cb326ce4d38906e0c55b61535d71470ef8bc6ef3ea06c5c2b678f9f54eb260f9fa1cc0e74684aa98346033f537bd8f9867c69fe6b01411abd499d5e6a082858aef521cb9c93e4ecd5960b6e7ed40a4623d14cc01c39ef48dd6761c18f2decf4b61d6f46ea3dad1c01992dcaa7a8f422090008abeb1ae223adac8610ef902dd7bf8d76f2783e612233fc63a7d88fdf0537e826a41c4f7a6e8615feaa72a20476888a1f43207275e7d4782f527ae40f8a4f1f86e02e5c62b355caadb7006ffd54b340ce3eb8b96dbb0841eec233ff8970e6c9963bcfc87643a54101425d3236b562d481a8acbe176c8735aebc087de2df6023a192287a5a5772fe745b452cece85a48694289b9a0dc02972ce2eb318d45b822bf27ea5534e7924500c9d0ce7f2d7501b86b23f93b8d4d86248cf87d875e5831c713a868526ba5e1c514cb3943f4144e0e24e6d76a3d69de148637994a9e8c22f74d5a69ac2976677aeb40989d5e2bfaab69b67aa530e1d5b4ea410fedab2e5580c822658a4c016c2e2f515518423a3777077c2a948dd7d7e733822949a90a1f952ae21e39ec80ecc1edb9a98af907691dcd3b390913cd7322975f0222c63f20554efade0d4ae97c19603f1e1f3f3f694e2e5fd004b208bf2683bc87388f66198f8b63bc7c4ea1eb2add684714f408128b3a07f1a1dffbc029e7fe541ebc9ab80d75e6263ddf4109c90d6397a915c042b7a285d2f31757a57feaa4f7be6994ecbc426dd0bdbf0af0c7aeffd7ee312309ca933da8f406c4c7257eebb25bf766cbad3ee9334cf9c7e40a311e2d4360b832900bbb8e51dce635c3da0f1a132eca40584d47f04ba7e9ade4c8c05f36034fac93548613e0d2dec70ef2020d7f22fc00292b5d014ca3a149afa3e4d3bf825ad0366f554da9c391d345b99744bb04908c2b4d2b16abcc76e247b9b055039499042f343a1cc2898bdf122de9a70f9f112f1bff84c8875096406be29a7a442f72b9c5e902f2768e94d9a60141d887e48893ed5d0769841d38c31a8633d232268eac9874d1f966cf359c40a6dc911d35b616df07dd14e12c6f2673d9aca1193e7ef40dd161508163fc96ce5a751c4d9c2a9f0c6bf7a06f5f3eba67ff5a182502067f1a2677e51e1a1a1a571f390d52f411691954af5479d1e36f0e69a3f286753588f2e2d0c52cf7c273c32c28a61824654b625f72019ec99ae1c0d2b4eeb694e30d67ae9e62eadde852ff69587d5aff9b8cda2e862a2c23a0e443decfa54279b2c05190aeade21c06ea97b6dfcf1c8bef4a979e314bc8009b4ab7f6275e7bd53bbfd7d4ecf76803131a10b051bddb375c23764a9014bdf2efa33a7797d7d2673c175d234cc19634de2d8dc316479f5353ce32c11f5a9780aa1d615281fd381b767673a84ad3ca8b90cf363f2fe96ae061d86a59dbcd6d62b016d63e827aa8dc5872760fb8b2223cdbd10edde6833a4c39d9c34d88136dfdbba75ab79d5f2aa313a2481a4bd5446f0add0", - "priv": "0bd3670f57e582eadeecaece38e27f54b2695eab4f89bda9a4db0545ab94dbf3622b6deb7f8ee49505ddf19b7348b7b9ac15923eb605ed52ac4eb3d06afb3eb30dd9a289be09d7e642627edb05a204a0821622368fdc73030dcff517a9f57fd4104c00160a3210e05fc1a42d93b7398bbd6038bd7dc057ab2b91ed4ee392c9d20c219092104ad4a010d84440da10510c3086813031d22250188209e4a43080c2858a962ce0c44160480d52940921473218c50510026664962c1aa284d9c48160386894c6402314114b1442a3106acc0202804046c1122e184481dbc64110c26898964123306c5c1845088505c0468ddb92900c898581a6280c9651243624d8202662005224034561b60c04404a13c0815818229b244ce44011da420208346d22278108c780c438511430200a29842216705c324a20b92cc9144c0a448c081372503461528251223564432804a4004410904462b6298c2462a3468c0c27818322491cc430e2b48d59142d111870c9466c94808843806c4a902188c424d3c08909c584e3426d5bc889e0462410892093b4841aa99059226193862c84162044a84d813204c398518bc48511a66cc1348858a60140162699464d00b5101a29110209215cc80c9c0024839429e3343283c431d9382a010852c2822da4c271e1086504a40508295143368ea1244402a264c9b40d228009a0a07091006a1b23701311722201825888508a166852863052124858c6919ac4898200104018211ca4480a3220c3c2899442329aa06dd92432038641a104094a8681111862d28090229525244669c90869911486c2244e41b2600c2040c994240c9389044002d9b000c88624c006291a880dc106414bb22ce2284890442c11356e14443123368218488c62c0254cb02991204a038449208524dc248c24352d40200883c2245b2492cb1485939808c4c28dd4282ca328221aa324940692c22801cc8420a1c668e2844d5890319a941023986491148d01484142304ccb3409c8005098060e432492580290c1b0310831928bc44d52028809a9251206091243498b24090a314d1cc14d54343202180619911019310a88a045049664cb1891c94490a084815b1401022588cb004d9b4471219164544285891289c2308654864c234961c21232e216215b429202056194408889c0858b260e9ca865c9042ed92841e1226ec32851cbc40c13a12990960410102993b0698ba48012380c1b312161306958c6850801621bb711e3a669e32026e144440016691043068c4888002851d002622489651c19204820429124080a404a59a284904285220420844690240169531000584465128244104730e48469d1004188b84d19c9708c4261531884a1300699301210934958986001c781103731d3441113c2408c02495344909040010985098a1400410666081744d498046240626080611ba9604032245a946498c49040404aa00084218201c1b8901040281cb3891a164508079220b208033311a2a628cc122a142231439640d9c489d1b811593630403405c92690d1244aa1188999082a0c94906402051c8040c9b8209ba444a18650a440521ab845cc408a539280c210904aa68411462c0a134948a86da1b2101bc8700a352410a04580b8119bb68980020443020a2293680b83451aa611c302220b318c82864c91462051c005c4a445112882213665240464612470e0b2841a3092898068493230189909dbc63048b830201970c93264c80092a4008dd89669a2880160364213332e1b332900990cd384215040285b104282469212a50581a44904212200264d89880c924401a48409ca40655a1485184165cb880da200121cc3681c8051da181061400140400a134710a2304908479262a46da2c09184482e00035089c84503370021828d640461a24482a4388411c20ca0822983c28514390224974093827023110a21948d23162e5bb625211386199900e348260cc6051b80510a130514c5000ca7459138604208315a0806d3848501c28199a821dac891091488898044d416892119481138049398451a07025200888190289a22101b474e1b42248898414248261c042e09912d24408ed0c06923966482368c829284a346329bc200a240252102890987241b88649c144d5a964192440a13094c00084d52a84dd11882020662888260d0b46d421629212646094690a32670401a7116c3f06a96754fdf828370dd882073a6c1775d33de8dbb8d355b8721d02e0d2f30e207506d420a21be34ebd72d17c68fa5563086887b2d583b7a3f69d80aadbe7783544b593170ba7a04a5aab16b93ab0c18cbc17043f4c2c180f9f16e870e693c61b391999f020743374f4e986399703a8734395286f04a7be13c043596660848b2f0fb6fed1dee95440b553b0a35988c604e7c01e836e44cc8735dffcc234bb8988d94faa561d071f31d4f732cf193ad5512c0ee358b7288473c4639c3cbe2038a05ad7a6594d17a61afa8590e652138c0fdbf30e4104b0ff5429189116ca4c9b1dac6f292b6e11b723b25f5166c1aab0e8784a121578d4cb515beaf5983e3f5d5ae6bfb3ee9ce3aa10f72d0ccfbfba718f7d18c3b5dc2c2f9ad6b8c5ce64f81c179451251f9a58eaf72090686990256a58bde07d6175e772bddfd2a35e0699e422994ca6ae4b1f8b2278c96b10bffd391a85f5e8b4d2ce548dbec4651502668ad7e76db5b6061696dfd392c6d30370f3efcc321bb92bf1226b75fc14abeb98110c079b439ff7888368f94f98eb21d08adb7c37b32ccd92bb0f5aeb1e41b0f344ab7b7508ad765f36a79a261a6003fa811b8e77334e9072c62f43b252af7b6995da072092e81e2744425c40fd4ffe8d8067f38c34ef8e0052b30785b37a71922a03f54fd7d094561a82c6cf18cd8f422a8464e5ee316d164c8eb7c159836c10e239566990e069718c8ad46b0e1f957d10fe22a82e8752b1722a5f3478d8f47a28d06a070c50124592999a4c388907756029e83375d5552d931dd06e78511130d9277c531bb21bf4a3743acfdfd54d4b19d4a179633f44b6e0c0aadd2acf29f690243c2152cbfca5f93fa29784b21c29aa23f5521edbaf8689c5746d68cc4881736715bcec9d271d9c875aa0f0fe5c1abd2a9a10e04def9d48de8385d8cea558e3df144de37360b2041ed096d8e3da47b359a0e5e6f8655dd8907c19486b9f614df63ae0cc1422bdfc1ef8533e91052f6f5f001d9bf809fbfb29e161c2587e95e3b8bde0ed815d931d7debf80d9ac0cedd1f5671ccbfb548b42503ecfc1a3b918fda3e53733ea7d4559bf0c8d5a20e395008dfeb9b0926d0c482c993d239304e368d000bb09bcbc4a29c13fc16a5c479445fc504f3237e04f25c67f35c553f63ec44891b41f342e2adba387a012f3440769ae57254e7059aa1d3394f4fef06f9ed0afea13ed780780324f7ae7bbf1a53f4e47fd3bd60084cb20b462ca656bc7c35e5b7346c4d909bd522b0e15d0a318a550b85c1bab8d78b6fd3dc281d2db7528f9c08c116abf455fd38b0b113d1b9cc11b47ae50541bbfcacf62d884ba9c8893402b0a345675ddc2805305ce51cb6d2c47aa1a25781cd3a15cc1ec4565e76f858fa7e082775e87c3211cc45a4a7fa3051cdfacfbd29101e662aed6b4ac5573ea5ae559622cbfb7e87b25780968af9fc70f80e05bf1906a29d08abb985dc005d30104dc71a2d9dbe3870d489e7bd95e9ef3cca068416788bee0ae9ab7c4c6cc2331f3803c9e5402de5982896dc9000943bd52c5ab1ac17894c17631bd815dc9aa27a3ef36b50c7b4a2d810c02314c98a0741d662b52186a02a387d351b40de458aef1de7639fd7124e3b0fb2cfae7c3f61d3efa3d0c9051de9067d4920b0e9feac0f98e1baaa08aed03fde225d5578f39716814d57a6e4332090f4472b5c55da9bb2e20072a5ecb924e1c6f39bd0cff3574629c5db29d5fd48d3f904f05eaa36ab10e336ec14a9dd8b8708c5d9e88b65d6b4584dc3a508c148fc73861ddae6102241b2bf2e0399d899bb3e618b13ce44ba09318bb00d5e0d7d7f4775e7e2a7ce3bbcf12a50356c26eb70d24826d8d566bef53bc4e4724fd71d3a8eb3302a35b79d8010f7e7d8846786b050250dbacab0c1a7aafd2caa4f21bb392574d5161803142fcf4555d2e3f18cb8beed78f5d24611e5541ff4a837209c4cf754521888439e611c2f1bca43b4c7f33fcdbd539f28700533e5a269b7e1e1b51952ff68d901a3298fdbcabe48aca047764e35ba13c6ac3bccdab14cfcb3a51861fae904d1e504f98fc2aa0761f71f37bc9d281adf0802385feedb027ecc897e5e91a7a4f7e9d4a7e96a740cb8d22e821726a1f44653a8134cf1aa1bb6fafdd8149cdbefa736873e2c7d402108c052d2a8ef0ae62e81854a96d990bea010b6bc29a326a90592144654f73bc01534967a9560e5a6003114b10505717e74334c1936ebebdc1bbd4944ed9276f9e42f41d2fb64480cff23cea5fa10cc1037d98b046deeb358a749e88c566acc6af8fbbf5666a166e9eaa4938db5aa9f4d9eff255ea03654e5eba09bca162897f0d85b6ad7efc44809b0068b3f9a83d68779c7c8ffe1bdbaeaec7359bf6f3f728bf2104557daa1f3861bfbb0ab162be1664298b2e1bc851b3c223f43d17d8a4d2f9a8518f95c15c8deac02d95083dfd913142821845224e91fd37d7919bddbae9094cbdd403fc2fec59f482ffdd404f232fc9ec1d84a6f41f041081a395e0e8969255f61599efd06be4f8a692d60ae9c78197f20736cf35937cddb51082fc44088492b11bad804e37c6ca62c3300104296dbef420260d49819f0c45c25e781c4c5cf261fc28ee63f53f7f260955bde7dfaf80bcd0874c9e61b764d3e535dc51dc57db18f78c83a70e429e71611089251dc6371a56767c08ddbccc7f929bfd17fe6c207ecdac9b2a1425b260cb386482f7e57ca50fa74627c946318e21cbc86e570e69799d3ce0a7d305e035b5d8e3abde12370714546e2632e452675e72e10dc31a599f695d5938d04fb5cf4b8929fd35a8bcc41fba583bfedb225bb6ca713a7bce47dbe4e9ffe0d3b96f3278b4cddafbf3351110c7fb4007eafba13e6e7bc6c15986d1e772a3f19c81b80e97ad12ab3cdf2c62cbb679af0fa7eb39a45b96daf17a58cb70be93d5663004e94b56da0adbee5c7f301d144365cbbd43586ea3cd3f1eace4a440372d85efa3b0ffeb35ccb652556ce9e3359534a9679d86d2db7ee9c67945d588f9fd32c8050e6430d01b2e441ab810030409ed252adc73ed8de814cb6c7973979af46d5697afaa59da6ad5980909f2c99aa364ffa77a65f85821c1225ec38cc59af46bd23aa7018a87871784e7244c9325167f4ee2a0e7699ccac300e4ac18c011166cc904edfcc373fed39ecb2e3e005552726451800dbea004b4bbbad207fabbe9aff5e98429b7c478682151b9b2337f2514fe18416e1e96962a6badb5290a6cbbe1a5f90596b408db651996dc94f9f54cb1f302b6bb0140b507eac3cd1cd5bab6f008a78bcde2023444eb49db9e5dacb364b6ddd7b4a7eb045734810a49f6fad19ad10ba8e87a320d7be9bdf722e020f9c9ae12749d521a3df2f1cbcbe2051894919b2a174feac488f1f15fcbecf5838f5239e29c0992f24aae48e39d9d5787b9961a9e03b8882b4e140a6af25880f547a55bfc6e75b55acd0765dc3e8d992236549ae260911a024d03a53f0a8b093c193f86d858c4a03ff409c55bae45b48ccdadd916fbb4cf44549513860fe366a06b22e5eeab26d32297c0c1e48b64e68a312578a9878e9b827228af6e10323b4bf32b149598301ad7288d6a80fe7aba74ad2ff89d5f2614369a98174eb2a093214ab7f20f6f0b9813190f32c63c3d9b38d600dc28f112211622b2dbdf1ab3750ea0a44fa91b9f0fda0ad88f8b17fc335a38372616b654cce474fe50ff859a9f7c25018c0e21b716a25c7d6557cc1a54267cf7ec7aff98583880d09fd2d70c10020bdf7db73f1a93c4463fe8c83ba3fd52dc62751cb075277bde313e061420dd896b79ede45f284e8cc599583879b441309c30e4339c63a4e13a494ba3c0293e25ae11e0d4b3817c825aa356bf6e09f834d3a10018cd8087d4efd054c18a63d6f56306103bd5bfa05aad45d5556289c16d6bdad84808c986560ccfdc2bf6a49ed3e5d8ea870d62a4636f6f4eeb76826d113a3a8e5b94c8461727763aee1dfe2ecafffcac5d3e656f1ca63583d65d1f11c857a9b08e37b0a59b83a9abbfd611942e7cddbeb2192ec9b44b0bc9bf84f12b16f643ad9e11241466f9e7f9b9a74414191359a9bea970b28cfce1c256714899f7dae74445a06bbd9deb848a749586c3762b5937c0e5b043ea0708b257bbbeb493ea205844615b40f8c48989873941f15fa7658e567e7ab64aedcc8d58cca98c7fcdc91ccab3b33502de237334c71219cbc81542e719f6832995870ca67e71bf89c62ca5de9884963823f2f5b64890475ffe199c734fc649c7a09c0a2f5573198a0bb3d66b78f1e2a55ae633a0983036fc770c44eec4d223510ca9ecc09206ab4d7af06f4ea755176951d14d564b7cc068f4654cee0396af74a6c196353d089d241e4e1109184a45e685a35d88e9a7078b92cc4b25276205b66e300ccebe543eebf8b358b027fc1b69ba69c1e74d9c8a43b78fc3f2c031f98a8b19b834e337da26518fa9f297eeaae2c9b304bca86211f7a8794659ad3cabcad3423174a93a36c8478d96ee0ae2c6ccdf03a5e4576a84d2544c207f4bfc1db158b858154e29a56d67dab316cd2c064ae20b7b1302ef3a051b6d4b2b279593b9c3b58e5aabf7a4ed9686a5e99129b3ea7a127ee3c8f6974aeb352a13fec56f6fc6034061d3cd49eb8d3ce768b7540701e20eef7500054fba69" - }, - { - "seed": "5bbdb968175f5a912df34125e5e810237ded6c6f2d8122e690f992bf32736721", - "pub": "fb06db3985739a9ba8e88c35f6e001ecceba30ca37c601b15d2f51f990075ad657df7367a496c0325aa47f4155c94ea6c0c079026b0a3e2b035f5a5468a7accc9c8657ffaff8e51108e8779a47a14edf7b6a035966e45e57ca4d2de691168ee78648f65dd648dde4476705e6c7e8a29e73dd8fb4bdc34a306cf446e5a870a2d702b1fe2a98b8ff41fe1c58b2d3850d9e089a449d527e8b1c5a51b296a4b0af05e29e2f8e9c82878442bf5d554f949ff20ddae3de470a6273838f9b4e6e93dbd94d872d2fdc0533c7fa9589090c9a04f1d00d8abb727fa5e3cb39cfd5e6b2bb23b0b80e5f2a83ceb5d35f448a0fc9be486b88adbd0db2f06918c0539f77bc4ce27549cb17f34b04d3df5fc2342af2be5d2942e8c04dd094bf3cfa97cc245df51a6956013e42b95246a3bf1049238d3f1e74647a86ed2bf3fcbf8d1f540b43c858c694bc1502fb987e5113869e4ce3d9270cd6e5ef9b54fe3a567d8f2216dd879b1d2d8a8b8d7edfa5952ab60adf0f7cd7fd8892be182bd02d83f4d5e810bd38199f671c120bf211e2acaa15b2d2fd157cd800f2706777c13939f2d5515c2c916e3a2a9666abffa59562789058de64ffc6d47094507591977b83e7c57c936d29d076f7198e6cb6cb8a8f5f4a5c5b00ae2039b6105c279fe6426a897442103d663f0d61a426fd68fc0962c6a6dfe1f06302f09b381a5753e36b97888e50cf0c424c7698844e6401ff6a7a6eb23247f8bba730b8b84b5c31ebfc0b8b7efec73b2bedb581a48f2d2d45c95d9091441adf1257078de4837b0fba93bea1a09c0fc723752449f2726eb05622ee26ea03eb5e7ac49b5b2f8b7baa9644d8357276bbf9ad83f4a9529fa5880365cca7e6a8d0e369d72f53fa6b7ecd9e7d8bbef9017785200749827a43711634f80719ee09ce74aff68c7c65ae3741940f2c407765aaa56cae5053e1319e066c54df850ab25503e228d613efc1164cbee5754867e834a27fd544ac360635b64dd641235e03b1a1a710435f70abcab6d46229d91ef49e374b537fde8e5001ca531cde2d927ce011185139f59b112778c1bbeefa739048925416019b0fb81f30ba85dc03fb540183317f30d86288ec064692e4198c9400523f2ede27ea32c982caba73d44912a28c57aab9ee6a62e8a8f73dbad8d838b66d52f45d7a8a96c72f700d67f74db5680b91d80ad1b041e65eb869cb79e267282695edefc0516305ea4caad2f29667ef56aaa24250c2d4f21e8c37a63b923439f57823feb7db3bff22e95629c4c73a7ed3642efc7edcbdefa76c0a2fed0ae1bb3f0a0608034619788b8bfd0e36a4b2f14a8baf9fa42b43ed57ae7c3fbcd300b4252cb3acca997b7315016176c5a8778b98b8a1fb72ce67b1669ec19bffbd8e64a928b7f12940580c0472175517744c3a891e786af5760023f7aa80de9fcb2bd923e51ad841f2a29fb4cb806c38f06a0a7d2a80814bdc66f1a6663d0675c6c518b7de7f7b23c8a7a9b68c0011036d23ce5d86231bcff9fd15e55c24eee9eeac1872170116af770f60cc33044bb0fa7d65a6d35863b79ed14fc1c7568b980d749d32983c2569f20e33d9b419574e9628183f7889d8f70a4ddace23ee46bfe1f710adc32aa579d821b07522028668d9fbebca239954622ff3d714927eaf2e87d68dd4b71d0062f042a7f9160bb7788b4d9287710a75e8da91c16a34a638fc4bacf6c90c4904771cd0a10ff6156cd26021e70447abd87b9f3c78c135aa0cd188062b070cd3b20f50c170a53b39984afc6e0cc01e0c52f514c6dbf116dfa4506f4eef5b6213e1d5e61a35c0c24e2a87d2674f42d7de1cea0e240fe9756395186d64a0a7cea5704cc307cb2b953394da9520315438b5cd78fe1d96914c59bf972c47eb6b98270faf6d7b484a0f18ac2e1e82500dd6d7f19130cad29f6e5c4f11ea4220cc0507305a7c73c95b6d9b04908520a4db2a7a6c0532b872e2ee3f323b367ce30141e5e29a8c85f74e65e7fd9dd891f3ecc2656e00db8858663b810dadf741820ea816c73062d64ac0826744715bcabfae27ac26c6181065345e94b3662a019edb6525c218edf74c456f07924741128ea61488b95f2bc9afb5eb1eedef890b36e467240f654a83d6f1a6950fa3630a1e702646ef857ecba10d4c99cb982ad36c1c7de980d11b3cea60d2bf3da9fe51b5f2abc4f564e289a2a334c6bb9971a8845aecab0a91d3ddf0cea72a949982a8d8a938e29ae0801f85eee029f243d9eef9daa1660925c676b0f078c5cb945579b966540bb73705f50ac0141b5313d1513c536d064f8b189fbc4ca0b322e713fe9da3b667bdc52829aae5e0b0bc340496ab3ed01cdfd9f278205e7c2d94cbe5e056fdac9bdf71bab9265a485c9f282af22a19ef033d6904ab4680c65ffb252cc94931cfdabaf97d2dade540916de07d1d2ec57ae12db381b6ec75d9b9551394686fa7f472b4df3087c7a3f2b2a7a118881f3adea30fe3e5e671bec6218a469adcffa115c12e1d3d020d1aa535fe4698bbf1834f05981903580eb03ef4490cc7ee9c1fcb78b16c5806fc3d4c1b199ef338e076557aa88e9ddef4c22578a1f1fc217f22049c154a6655012d7d12e9fec604207e46f292575aedf2bb7816ca5a51a3822c461bc9095255f88089990d6b0aee80961d1df4fc22c505ecc717ff87b9bcaf8e23bf06729cab91bf75411af4ab1cadd23bfa1299c34abff4ee725aa80ab5821cfa8e170a6dd856530e39161e31d3c0f61cc03c097eb996dc2a41a9c09ac0cf63d1666069c6ddb69f86c5e72bdf35b555b4ee090d02a23c9a822b210c8cebbd778718c000e0ca3470d49b6d023e8804bbb1cb901c82b75886f013290957d45da1c26e454fdc2f8519d230f69647d1eb7078b1c9b0d828099c85f8f1277baec1b50cc61fcf846b26946272d05d8d3bd14408b3db12160ed6f5be9dbec8d6b9ddb368e1c08d83ec4226eb8252406341f55db347fe90758ae04e87c07a316ada0824b0fca2f3b7412a66dec6e816975388cca22af8cababe6b51f1a6a29deaca540d85c1644766e8ad2a46a242742d5de90963a4556542f18d8211c907bccedf80786daef419065e7a538227138e690ee65860875fac2279fcc3615ec8acd39502bd5b9886707765599ce2af03e1e37281b3677a26564e48e77c073025b92eaaa5b14d3326ffc83e4d82f67bf458bbec3768306edd08ae3d53bd60db50a99609976d03be2546b92d9f4da96e9c143426599425aa5130240baf6e265f76043a2d35425bc7e29e6001b54f3c777c1bfce023040e8112b25ba604ddc3ea5424e14c405230882e1b28f7919e3b07c50cd590a9387630f0903dacf1d437d4f87d310e47ce0d7291e94c27056799279abc3f4003ac1784ecea9292f7a98101044dabda969fa30e18c471f14db6bdb1fc964501bf739bfab72c656c878611ce8a6965128f732871f04935522a8b920bd46f1ce037961dbfcda83002f1521e6a46a2d79bc385d9dad57b164829382df17ddd68d6b9214a4bd39a5ccd18f6281918c3ae9313eda543fac57d1ea97862f68a3ca086d693bed4640d861b4f06773ca6b6f89b48c6d7da2530cfe0a950155746445d358d7747149c3da14419c85dea4e37e07d5871d34910cd82042272aa25476ed085b9a09bba", - "priv": "fb06db3985739a9ba8e88c35f6e001ecceba30ca37c601b15d2f51f990075ad6a9cab6b5d944bc0b3e392eb551a2c7efba3f6d725bc8187f08ca558eec91b20ca64681da6237ba472083bf015a477dcc5f2b4d9e43eeee2fc6e6b656ace995f0b414c7c2c13510c88795e61d6f2167ded0b288e6cc5916cb1b0d6a7ae797842862066a0a126ce046651b406dc4202819c804e1b868c2309104c4714424269c0640129325ccc06dd2348c8a10098408911a374802b068a1b064040185c33265dab089401671910442c1444a4a4428d828821995691a270a1a1172c0c20c14b1219430261aa090a09208134430833092da0268cc806d03c02512b28dc8068a649865c38408c94209230360d44442d830654a449243c4411102121b062a6134921ba68d19a4308cc625a10006a3c68d9b108a54c40d51162c89b85100492822c2810b92082044259ca00c623668a0b40c5b983022a74c082120c804625a380a11484189088c4ba4601ab7602280111c340c1b131049a205224600a3827158c07119c8105880451ca030d8486909400c49848064362124346a4a868102270a4b308e0a922ca102914b8448a128615a408e242011539891c1922023232a93402a49168c1823401cb66000348a22c32dc41490d0064680a645cb086d00454141c88c24c56c1bc52dc0024dd9084c21215264b2214a8891c0220503c88c249691a1241099c25002a52d9ca461231210c9045208186653446414086c58a62c5bb8045418481a298504110252a281080881a2b20562b44413c93088145280a82101b56949326e98b46919847101490d4c22104c06259cc085c4c26813122c619428c2b4458a38318a928902a541da24908b4804d0102900498ce39460e20484db406e0405661c094ad1964520909009944c0a182d61044a114982c8486e89a00811a86c039020a0160e5c126151448002208a9a400ca242440ca084dbc40563464a19994d09262c19b2400a2802d292200b264013c4050c2192801205a0c2908c80614c122909b451044348124426d4a440cbc20413498d1b2166090742d43652e43852e03446cc108924442accb80d1929450a222510c26519250ad0b01104c324a098451b8145e496049a308810319120347103a3280c35465b826802800dcc880c84284621966d59006153c871410624a14601532480dc10851b28888212425cb60d12998d50c685c0b40c1c10441486900a128d04c82840c28c0a398a221502a32220041230dc304e999665a134101308408c264e819468a2c26061460a11066c1c24641987400c228a44465021327009244e91b42953224402b16953a86d82b691db9401a304000c0588ca107098884c9c8281c8086ecac49100174694484454366053886d1ab865c0064c4ca4250ac2505a448642284603b064201824d82402d0166040280580a2498302052428311c047201c268dca628e1284811074058341202230ca0348a19132614438011a2691303041cb631131445989249c898858a322ed8166002c98524a37010478459b02c213912e204410103210ca3700043649c8844ca86000aa6451ba82943a2810aa760032524d1c46d8c068423036159b22818238d53c4300c148e83844519c9444836858838660434699320602447800948820b49311c83285222710480685a026d5226659c2844d828864c402653223262102aa336488a202083404ae33464d4c881cc42216036860126645c222ec02825a02252a4a200228750c2a4250b318a99c07181844858c46cc22228829490e3467049b80013c1604b4225e0c62083b465a4424491140d61286d5c4430221511cc8244e2420400883021336141088088188540324c0395645cc601db243009a969132845211248a4484d64102908062a49a68520c64140440dc82450cab29140422ad146049b942c4ac8281836444bc6081a26915b002ad8402854120e21b640a4120d40402514a340d8065213b1111a89880c19829416001a484254426ac348065bb811184010121865c418201291480ab020844832d2c009db988108272250188c0b368de4a24c0194512405701c0146c8a210d024415a168e0ac268a34820d248091c018053c42962c688841445012645220752d9c66599482a0b38681b4348d3182ed0a86400c381c9424dd0b68914b9711813921390891a290a4b484a0a21003739af652f3791fffdeb7739951a9bae0e392945c55a0e8bfb1714185ef7820925530f144023a8f12c6a2f948c0a1cf14bbfff44629a02b72be00e89d140d4df0a6e2bba35e215f60e7e7f7c006edfef322283fc0aae9603a3b5deb7b7514a6c73ab8e01c9ad0ac4b5e3d68a09c1e4cd618df4b27e961cad46647be45d362b1cfc57e1b112e2511cde6ec69123330409297340094f087d72c6c1dff5c1bb1411c4f7874e0b068e69364b9a361444f844429fb77229eb098c427f0599dc990f5681ffab2fbc1fc3df0b05234752da1aa8ef81f86adce953f00bd98f821c7d3602bf79a9ef6ab818ad424aa1ebd7e164a4fce782d23d2056badd7294940d663ae3773d64415eb4b59e8f4232093eff02c0f96c073aca5be370f25d60313c84668ae8d5ebee1487a9f89778ef77ae63d19fbe38f02c6b39e99d5bdd11e53b14c58a31c365e7e26e4d2a8fd666cf89c624beeddb4bef816414672f0d1369527b99def915a483a66ce84f40435f81061543e6793a7e423d33225078249324ae7b4b7cf0e7731cf33eacd9f3165d1dda8358c87c0cba38ae6f28168a8699e580e2b7f28e9ef6c4d958236d9ff521ae64beb1767a9aee728ca11dd9b287f9b1571d92747df89e5d878a460cb2cd52a676cb0040eddac85e332f0d95b4e0b60f2ff7da07971beaf6f64b4cecf916011063a77cbb87213237e600c1b2f51816d9b1e00206f1653bf1ad444c03c60ab6876f14078ef1cb3b7d2df6cb0f497c05d6f1c4670c340ff6e81d28df9d74e07343dd439c7ec458bf1660135869716987887f881a4223b161b8d7a19e82688e962740ec2aed3b553ce112fcf84a8909542d1272a610a69de71e92ace3f3094a375435b54ffdcec8b4107bcc2341d0ed9b23b072d946a05b3e98453c592d4a7b4bd6edcb86609351a4115027448f3018e29f20844121d592ce5f0e04aa74327b96772b3b7c520f03b4a928bd63b3de8ec90118f9dfeb11a721ad217c95a1f73496a23ba025a8af440e22fcc16e6264ae6274aec22632df252f1348c6922bfa3b16fce9bf2360845ad8e187e8fd99cccf9d4dd6b36e0a8d78e11d33a1b9b054b6428330fc1a5833abfc9cd5a821ba2d60e83341be0383c5ff1212b8bd9049a0fcbcbe769b3ce4741a310737d9ca1ea3363740646dd0f4987a2c5b903db2534217046f8ca360b7db003fa1abb08c6447f464bc35e55cfd0891afd6c3fac3cae899e76412877751bba4f92251fd0037d7a71ee752116231fb533f492767ab2da9e8c1a269c27d7d30e1a9aa51f083264485ded056f558798ff1ae6c1c0717c246b656611bd4c7b3f98610bd08cee4c4488dd641fbbd745052e89b0ac541fe71f799d01e10c0ae41032feefc9f1abbff86745b62f409276fc76ecb0755529005d372afe95f643a6215511e0acb43fd144157e1e863f402ec18adee79020ecf3b26763e13c9d1aa1de5103840cce216035c519eb652100a5ae43b205ed375c82078fbcd46543958cae2fdff7821c75c534e1d6311d5ed218179a347184205f2ec8c90c1bdb51797c0e97f167d973b6b080d2843109acbb9aa16faa3e113019f3776af906e08d969de5e6332447d0052507ae9e3a5e214ab48b96a06a93ad2785f85d305d1eacda9a8902c9013689111f83825fc6b3fcd4fecc1de6b80216b29ec78835c82750c176b01e5d0e933342eaa19012ed04810b87a5bbc05d178fefee52b41657ca0b89b8a87b5103b91b190b0ca4fa9b01863cdf7619ea4737dae4096243a9308e9e35e695839d7e2810a5accbbddc004eeb2f6651f64f9228b029712613b3db420a74416a2b9a1342c7a26271d92377492ff4704ee2dd6101cb8697b671a606642d9237f688505b6b070d0535dc6bb0bf7c6d9594666e121c486f492e9f5301ed21df719f3c6c9cbc4c7ff519f8a6ae6e65d271d29d31fe2d5e9bc726d54b9dda96c19d68553bb586dda58fd4ea3865795ad75469d5583f5c326ca589bef0ece84a3571b461a2b9452f9dff31c759fd9a930cf99b3044768986556730d0f2db2c3f09d4dc0e7d27e983849b11eca07c0fe3b919a53157cd8780047335ace8770395063e43c8e98b5496f71f0ac3c494692a713284dc2cc4a5cfedb1387ceab7861b48b234669fbe85c79faabd13c92ec063d5b0a435ac962c3aec42f7183a8d6c6af680eb01479093e83bb8d581ed072769381dd1b05df0925b9ce663811b1f993fca76f78c0f120cbbf342f49eda1ec068c705ea86a0b9c6427b37375854f1396647a99d0d8ba94084c4040ade02ad97876b8f924d4e0e084c8febdc1eab083c9658ba8ff9274abe2cd82d5e0d2cab1f4b0346a4c8036ee3c26ab9f56ac3776f3fb86c52a7525cbc6142e4015df569d4aa48bb540c0a65fab9b6d239057829f757352692562a0f536dc0cfb0b63ae2d597d5352b108daebfc4a09c7356374189671493ba638090406be3ec01d0c3c7e4306258ac1c793118e589c9a6e8c9140a1d1f8b0fc35bb309449408176dfa5e2e0384c9ab85791164e2c5cfb034e648b5e94bac30015fc440998b52d9430e4783134d0ca503753d1441c6303adff56f38a5487eaaf21da50ca937217ef9086165192b865688831059f50c61bf3ed4fb2f53c9160db87a3e6b4302334b4519fd71c028a2ef4808ffc5744d88a854734d6da5d0a0bb27313aefe3789eddcab4fd4602ccf96e6082708a147b93dbe40bc3e2d18359dcaca3e832c67b8141e2cb453965aaed10b5412a2dc2aad954752d44f7629f78ef3a03369a8bba32235529973666caa62d7a1a25eb14eecaa1725f5832c77c78912b9167b8e77a16a8e000da213b1849c529940491e6707a63d9228e4dce1c3cbdf804436865d208035d059313e74bce48fdc7970ae82569e0e35d1a0318fa32075a2a542b8074595b4cc284b53c7a380f5c8774c60952cc92e54e6fd9d466c717ce25cad63db2f5faf5bfcf6e6d5d8d0bf7973d107a264c9ec8163ca282ed2b168e10cd9da33c1dae6a4e9f305186d5b5af229c6050a1528a9caa640d162720f1d5d83f6c8117235113b526607be42e10240d6027eec16ebe0a1af1de205e6f88cf945e8dab79cf646e3a3d171c79102c7b3e7704aa107b3fb71bbd9cad85a064fcf1b4936385a566115fc47b8b6086de610dfdd8e174142335403b67ecc1ee5feae9f31878e66801a16bf579eaccc896645987ed9aa9de114aa96fab34cf3248b1f638f282f51f027efec674bd1fb96323bce4d73c5735955633bf0cb59ac142f9ada65f00d131288288c453621ce559dc9963ba98541ca8fbe85079fea89537c0c8ff5f7300dfceac900be373a0c16b5438eb0c24ad1ed2bad77c1094eaf6822e7e468c344b8f4d3bd1ade74bff709bc33135c462f6cf338a7a1d17feed4d33b510bbedad8d0432aa544819b041f8353800a1628fb0af5aefbef6f1b5ff578edb4c7680519594ad6eb448d7f91425cb186eb0eef71e1a7e4dd9e3e0a1bec76efd698757878df67002179f37b298af8efd033430840ccc6ea7fa693e8d3613361d5e5e0d31ed33b36af0fb023be01866385e2b99676561d47d2156eb51475e3c0bd09a43f78405455f2d9b6007a31f79d36486cb807282522d6e1652726a11e3dcfa50a358631c0371061578f8dabe3690c05811630deb4974f895d093c0155ced6fd5f2bedc537091c0cfdf7c8aebfadeffb0c846f3f2d6fb16c15b06462232a2facda1daad82ce846f34acbfcee0e232ee1ee624546ef54aa82dfb9918036751fb3d0cdff944900995b00c41aff70766a42bc59057a66770f5c6ccd1d69ce44fde5e62f7375968ad8e9fd073548fd8db253c1a968f5b6a7ff97e18cc87e78b427e0d61dcb3121f393fdc365e6897d48cab1d0593150b069a340ff3a4804c1c750c26e813718f4491469f204e8c205d64b2ddfb5d68b64a2a413f145a60fe30ad2323dca9b3d5ee539f2463bb21c308878a06535060b2d269ef57d6775c4a8cfe51eefeb6ecb87ba84b1832225c80f6512e2780cd0fcf6dd980dd830fbbf8a36dbaa90c15253d37524b4d8956075bdabe5e700cd2f62b142f8a700e36afa4ba05ce066afe2cc5921d96f51cd646e195b20265c16c94c816da25edbfd4427ef0c76eba3b5cd679372c54e9fa41564d7dabd843d6ed299699fd44aec72343519f58331d8359189c79f78a8a645e43a2d34d3414a18154d71844c50429cc018b6da1acd4e48e629f618e41ff2b9d090ad1b1cc791032ef96a2afb1f9a36ea05bb9fc6adcd40521f770327c2a7e26df796d6ba3b0625b5ba09cd2f6cd05e13109e65f2188dda74ab43f799a62af9a6ea7fc6b629df28e4a83b1d03d126c8c2909f8009bf3218f45d977b8d5e106a479d161a64cb543540310272422b1c971e126c4ff8e0e4e9af8302e183ed63bb68d6f58f744ec2e963d9c33d0948b62454610869064ca36cad73f3b29c322c96365719bf4d1bddaecde2d57735e83668dc1ad1532439875b9f488250944fd1d98d25db39cfff556b8b59f6a828632b15be898fd605be8d3be905a7b49c02fada7ec2136b78c9e18af379ae2dad5147b614e3e8433d5e04a71337484bb73f74203ac0aa50e05b61cd1c1da62bbc65b231348797b0114b32d0f7e2a3a5f213848d248854e00661fe25dd037b7cda57e6b2465c37f47e45217ce52d5c36140dfee300216c" - }, - { - "seed": "31330c3d15f755f6e5fcd9f11df597e048f71a4f8061d53377ae3907dff2ef1f", - "pub": "f85c5ea5bf296d8cc3877fd906465ebe54aa44d5f8e9efb06dae10e2382a32317f2cbc438bf0056e10cb0673620d880ad65da1957069d564a7e95c7de22687bb5c8eabc61d6de1b7ceffb6cdde917888ca294fc177cd196522b72408c9d080dbf2b071daf9637d5c4845dffb7c44eddea453a213b33a7377437029362f85e370f5d985ba3320d398d1c86aa5b1682e47cfff32d971ed42dce7d993e6aefca9aa96f8c62d83313fe83418579e963b105370916af99b6ec54503e465e62bd7669fd7b153867c703d8d3e6a7d2c93fba7094d183617f7b7f478de48a77dd894381493756ee9d4821394b8e0ca75d6b3b8ec19cb43dbac68a16445f963f5c675a2dad431da332954d5a0e1f216e43a00bbab5ca4c55f0c76786f75922cf1d52de36eb9b80d075b436f9325be332a815ebcb610ebd787fe692ac178c05521daed4f6382c5685c1f41a330ffdab185ab246135f4181603a606ed25793747d875b3b8ae65a51a844842947e17fdd62491b92592c29b9f731257884db6a75b248f7e639c6606718cc3cffa0bf5db48ce2e37ca8a4061854fe66cc2bd6e3e2fd69fe05a3e914ae0569976c9052f278ae767a73949442bd653535bc69f713be7c710a38485875ab9a1351dea2bfde9ce6f4790fedffb302826fb21bea1e87da3b06b2df1e7ff78e7c5e556ad6985fbfae89d667e6fbf9cef7b5a1e355ad6e3a0479774a369b765c465db25ec5c616b761539f09db9d1295ec28f287798164cfc56042471cf98f96a3670834cd128fcfbc1beb58bfa9e10da2851f31864c8a2a67a0ac069f5d656b8087f6e6d98ae966a608bed5ecee9bfe5393c065e830e53c7b7f6c0373bb33b497ae284e6f78e5495e255d3d305ca58da14f92b06cd0b8c7808fa00701ace14dadc2a39d372e0ae46f47060f0afd58544f2c68383eafbbd97c932d26c7f89c5261f509e7437ce9489e8bdd733269741aece93bd177206937cb5c5da50e5566bed474df943830926d16a7e5ce909497b0bb46ff494c2ac5ffa0ebfe6172022025b19d5f7edd2f2542df6ad5d58b05499af62f8ccde064ed473a8263e76fc8d40026688030b0c32829fd7a9c0806c82dbac155cd48bf9518b8b02ad611f2e5fd317be61b2d51e1dfae525669cbac2d5998c920f4f0eb9a9b846156f555b580f33742c94bec58c68dfee8b1a89952f22e83a44a1637e2b27c6c1dee417b0c80b93106bb263090806d58bc42bf4c0e5a34479967815716bdcb6f89e54ee0d4fe4d82670f73c8123e1067805854ee206fe77bd21f4b7f394541e28777fb25f63e8c840fc66c845ed01a595ce9acc7f825f2f3f1665e4f7d7e4e87c019fc40885c2394c91f2d6499740dc58fa3780e340c864bb51788643b3b2b6664470cb255135d8941599cbe0ca80a9d4da3add8923a86e1af194db4aa162cb9a81f7b256d0087d24f59288563df63710bb82d30d075809d3bdba7af0e288bd4d16ce299b384a8e87557a3b7b55958d71924de86f152efbf5fd70ca211da7d87e5546374cbe9506c25e70daa7613343e2d2c46be7ca21dcb000a4c30a42b4f3e236951ce8c5d5c5c1e49b0f52a9a9a4dfec372f1a409a771b10af22f41cc6abdf002db3d767c331e1fcd2042afa82064ddfffa5157c8f1fdb06b0c467ea6fbcf678c8976cd8716f9cf77344d1c281c1e4715b94fab4df826997866750aed4a4c5a15bb59cc74d62d04c641de5b63e9fd44933ec9207e6450d86676d6f6eb9797f9c2987893434886c15a48f5180c5dbf5bf395f90d2f90668c7bd322e7b9defa67c15722bed42eef3f5591ff2dc2f546852c92080a05a55a815c90a15fd59fd4fbce125aa0c2b4ff6fd5db7de651177450a77a77e4472ca8e67559f9650b0ca8b80c56437602c5f55d45d42e4173f5ed7047eb307136f7fe26f0964e5313ea31b3e6d4c62620c1959b6b123af66a5f4d392f249f45d5c50b01fce30f15098a90c7246b8565565a9c3ed3cff7d353590b1b0304a88213b841b848c4607d61a13d0bfebd7283d4b927e2f7084a95db81ea72f8580d54cf76f6ab549de017fda9efec6362e3231c61b85478223f8031ba9e4eaae0d6c9f5218b244cb9e106d397fb66bcfb48c5bc9ff2bd44feb9719126c4fb2fda54d615899c503b62d3b05c1c1ce6992f9ca9b95637e19a4034da352a85279a16a69d3ad7abc92ad31d621e7857700c53c7bfbf2b7f883559e56da234a593f8b3ad4d655d9d40281c68a1869214c7aae8548097d1d2d7139b27d3f288fa0a6910693ce4e0073291e026a7f34389e3c5650e4cc10b897cbebc81217c11457773410eba6aa53a0d8334c2dd6151711d45fe7854f30356dece25d83be555391ac98c86260de3800a6ac170673c73cc01598d21c40af5dbbd3e6ed22a9299282de7a075ac436dbd0585ae7e5786945fac53aa28b892376f12127c8c4f25a08efd18b1aa329cc947086f57ea044b736dd6ca252ffc7604ae17dc5086f33c681f36ff5284fc32fdedfaa7c59b8d6367dbee8070cc793c07ef3f14accdc08a071b069024ea13dc03b37c5d1a082be4a2684545517a416f3884e513e95c2bb8a965579e7265a6afdad3040e9365f3469613c47e53ec9366f3f60c40f2daf7e9e23c414536565828f51ce1304035cce7deaea24db2ff489b0924ec645b9858b8d9655a0d00d5447483c6222a5f35b8510f0db8f12dc119c41bc7693d0ed68c24ca24469ad0e465748f7d67e3672980a28342f7776100bddfa399c5a23afd2e487589779de54fcc62292582717fd774d5ffb6802909df66a513e911e311bf21007bb9b6495165bfa6a7abee60fbe9ff56810d053e3b293fbfb75c59caa83f45fe8eb7e759617db42c25d27bf7cfe994ee537c7806bc64a9eea87c0b669c831bba25326b2baa4fed6f57a081a2aa3dd18e5a4ba13514fdc5d1502fb18651cf8b8294fe7d8e63028940220990939f92b6896d493b8d76f94fca7393c61a26c726455801c1db8c702140ab287576a940f784bbe0b9a76ce9d316f8a433d40531cac98fca1685f9b44c96055b2f9480e5a0b9170f504c4124e41744adbe9f3d928591297cc6c628bef89a9223602a8518f9875474b098fe206771f89a1a4fdd9271d2cde720cf5c486474ad14eb113588c60a413e022f9a92d7dfee2338a5ad7a6c4aadd1b31a41c043093a9197f1c5dcf59e0395c831785dfbd3fd3ab3accfe390069b18b63e560d56ba70b68a0e008e1622bc70df53fa94da6dcd03567fe6a12702a6b49b2527a27897133924e13644c7d8feef1e5c0b7859dc3dca125ac2504c1db2adfb2117b5d46a479d7edf6f03d0acb52d06cfc9cc450b9f3a52c8569cdda415408849ac341c136301e7c0a426c54b2be6bf40d924f937c8bcfc3d66d3f0af981b6bbfff899791346aba0269951480ee5b1bd1971ce9e0b1a56e8ee006feecd4007bfa9abfdc88babfb5cac3b44ef0c69808a7ccb132b6d425b8e549a8a5c98e2bedea81f60ae2ed4963c8e2196d14ca3c5d9308e3ba9d9deb70015858f5a18bcc98437089bbe6cc33ab2bae69575810074c2035b6815234430d4f5f2bf64ca2ee23e0577f20a3c6b9240e8d400f1eb8be66389f2a297af17487b385e182f44d26946277d9adf5ba70fb1e626343bda308ca5c2df63e0", - "priv": "f85c5ea5bf296d8cc3877fd906465ebe54aa44d5f8e9efb06dae10e2382a323118c20a879980f4829c2f74468a8f65ed91bb581a36ca2153a25d53a5760fa5975d2fccf55a7d4b2af4743ed8839f8e6ac4f9160c0e09b829a90409b5d4aafe95de9cefa78776b541c3886e0ffbd4373df1637ede716dc366534bd01d62fcad24e446205aa4241b056a9bc62924254c241006cb4606a21005c80406223764129928c83045608080d8a88459820550006521c99120186c80226420378ea2344414c5708980499c042e99204edbb21014405180920c20b7801c064598949114002141c8400ac6911b346d184909c4108424230ca4a6901b4229c1442060489214357122438c88046460164ae4246e8b8201db248d53b06c090222ca148cd842451916510030060226664096908b487119812c0310491848691b1390a480455b168d64c069db0009a3029010194cc29250c0b871122662dcc669892284e382292223269a062c41322d94c26d480005102071e24050d02804d21060e0848020280251829182a2445244841447000a0642da80709a240892488510098a48081110222654a468043421e40069e09010d4b870223104021409a1228653140142a48c23a66102a5901419248a9488e01485d11849cb2609d80442c94408128321cc329219316800386ea3084924c361c1347289327010a76810978021a20d09b19049868d58a83063b070d9c48d22108d08449244308664464e9ac62d0837221208281ca40552126a1ba70cc1944141b205a3081223a1299932252103418c26600c1932092888998665c12444e33651813451a1c08923238644086623c065d2960904428c1b954d439805992681cc3865c8b08c52b62112b27009b549dbb82cc010720c402220211194b8610b08308a206d8ac690d942668b8081ccc63123438dc31010e338068c2064c9001049a00080b869a342211cc12941201183340901b864029100d2a841a1002dd3284ac1c4701c072559960c23834460840092a085cac46d81c4404044842411450a932d0b242522400ae0882551489191128a01c584582830d88021a2100d98324e914420c42472e0442e210985d30291004570c9208e5bc4490ca8614ac46c12398408c70c04374e0c358098286acc42100a180e0c19314832094aa22014464d401811a24026d8a604d14441938000192192e300321ba3896280492305494a4830198325a10684dc8845849264198964194028113889c1226152c864d2c084249701033268a330444c146048b444c0b631804811c9b40c18268ed3c68980243290a08100248194966cc1a870a2043199846950b08d01c12dd3c43022b73009218662264409970921328583086d6008804a042053464de24630d0488e20084691484192322044880852426c9c4890e20204500852d81692d00092a1a47062124653b030e1326018a048649229d92480d0882811a1010cc869994870194952dbc84c84344614b78ddc3441e4806821984c20060140164c42b2650a358da49668212590c184680a126e1880714896299042201a0828c410290c274823308a12438281300c1a127122904403326198948d1b4066a0b2681a066420074ada840d03902d02252909074c58a06d929268190172433465411068c1c64483426619b08c5004711b2002da986cca064a8b426954089099b24480141084b62120100509492e6022005a928804448920b865a20249423862c4869083208ccc3408a412688142658930812440020039910b163162b69019986d1ba650a23420639810a3462091406a02150a211266242690c1460e1911810ca98864307148a88581b2258aa87163148e421470c03228848485caa844d0b82424a3689cb485e4044962a82809c590d2c809d3c468d808608b9264c126611ab98198360183224c43483163162c1020428090112295049306814020000c2952943205cc025119246c50966cd01431e3320a60184e03956d8230895216451c284860022e00334484266ad81672248508c3122510016e418211c8024e5a00651a392c88306e03358013298e04b77022c5104c0821102840c14646933871012471e44025c22441c21080e38428231820120350144242114589098425dba66811820d20c80910184a9320420bb308d90804d4c244caa8449430266342401bb44d1295081109521c31445f0159d4da10a62f703134efdf3fbc3a981125cc0255ee0104f78261cfa295d3d1b1448e3da3dd087f324c3d5fb5b2a83b746544ed2e4208e5c7bbdffa81194c5b879aa90732452d127a82bd767ced087a89bc22ec028be4c99fe79aad50e160bf9578effd96ee70c059a39bdb5c1fb633d05dcaa32c27bb7fcd9e5fd5be9ba256ecaa1e04efd6b5b052e1dfdaf93123dfc552230e05de8f52a0c4fa6196727bbb7d784115e43210d00d340d01e6d38d45876917cd6a80ea381aa07607de3c5817bce78de4af43b2d277b4acabe626db93f8e56811ae00180d36e9f1acd9a976b0005c4719230ff2c31d2520df60bb8739e54b2a62b209be0287b965ba615a94fce07b55cd36b294fd5896d8d611d01ad2dabd73e437d751159c5b0193d303c77e1c5bb7c88e3c74481c58018f2832ace8c87f0a23e0b70e9a80c92046e0d0dd825f2e25a37a2dc4799482827e9764ffc8b2622d4c527c7ded6d2c204c8222b37c38d1b095e6f83140e44ecdd9408044a0358d8c859f25b93c19f972a274092365c866e9d18c8815769992faf7d03b15d1e7c11c029653125f7c423127dcc5afbac49768d1b7d38c2431386703bb3212f3893fb2dccce26f3a46f6233de2b1dd0b8b31970d0e3120341bb40e9f7aaa62639ee6bd365bbc99ee7b251e1bf288963963bcb5ef06237a6e024beabe0f72b78b0f4b92c92102c696fc81d6872de675c4eb82979301b48ca9a6e43d092199c50bbfcecaee64b9cf31dbfef25104219e8d51c910868ce65b95a72620149a368ba3dcaebfea448c07fea336f4592154fc3dc87a79776c5b676883c0bd647779ba04ad98c60e06e3be7296eed82c40327142d78a1d143425d92cd46f07edf1c3768965902bdb3e0ca70f782e89f8fe6283bb861896a6038e78cc7cbd2c212bc10ad77135a97445246c1230c95b7ff8de1bba183823278396a45f91e7b96b8b129a14de8b0b028e6bd9cfc59f4aabc04bc96a34cfda9caf66253437bc2f993ff778455f81548f999c9e6b80f3baada7d722ef86696057f75ca840f356499d5c28c6c227c0db59fb015644a0072127fb6450ec8931e4307216763f9825e2c1907f3d7d162f42e6391f3faabd00bd53b07383f755fe04ae8ed90320d7c255062448dd35c442f1aa9a7529d94aa5735c2f994d024130b975d3ab7895c9e86c183c4e6f74a534808e27ed5c1472f1bd77b94ce5e29730cc23b23edf51d63dff5d71bca09a518165fafbfd70504c2cd0ea4dcb55d72b15e17672d8053de978691d78726845919c663446156dee8de8b7c2d03908212a3ea373ca3c2bf186b2a000f60912ebea53aba80c16ffee02073bf2202a7a711f1d923b69d339188e011bb2fbe50454e171d1bdfb064a2d4dc0d4b4517340efddc616c91f8a51bc35c82c56e258a5780e4a9fa661e66f178346e9f0f9e8a7bddde28473c1708ef9e6dc60f66cfaaa1a44ce3d6e4759ea658acbf08cdbc6db9022267f0c51f10111b7ed840d690c1da67ab72cb9b6f86169fbc7e9584a1d73e05bbcd50144870709768fd0c91eba70d85d1dc783aad1aeed2df2101fb70d9880b9165ac2376e121f22146e38b2009a976e9504d898116e9d92bc68f86f8a47ee93576ab1e68e530dc04cda2ec2f670db99d13584e682c26c7895339bd80e15c9192c68f170a52959db303d0111b78a1d2fb5489d25d70730f26ca885493eb4e3d1bb2c9da91035e5f558c6f06a531d8a0ce517d5c72694f9c459f9013e81edf3f1e96618161038f90e7be79d4f170c94f953452f8e26b0220a8d0504b2c689b86a42002a9736e629f3dc4b34e68a51e4d767677cbb38bac8dc8a848f504a7cbf2fd6890ab76c1c980986322f6b800ab7fcf09fd25892705905bb21ae39997dfb8377e6e6f79118676826b5a0c9190d64151f9a3c50c32768a4880d66afdd423952a53da8e0a8546ccdda8d3527d3a13e1fb297cf9cb9b6d08a8538680af4fb1a5f9b80a2e7fb59334c32d17e87e1f87a680d6cfda2305bda345299e2e3ec5237765274b2bbe64a6d65256225f1c599395d573b02737f31143260b973afdc120535d2c354a1fc9c99f9292e6eca1f5aa6db9478a2781b017bdfbc70315a3809af75d35079cdbb81ba61406520b5023ae220c54c95e49fbec78f788ee5e3d7849b5a77ccbf956dfba3f2a1a67361ef2dfaddc9407935b2795764d430ee5858db34150c964cad48680189f83d873b98b07a710f22b63106cdbcce2d893bdfa70d12db70ff63b00a67116e6d66bc396f499abb3f4f7eeb655964968a24e3a12e56ab0b2823b5100acceff86d3d4655c8188cd685bf21ea87e3c6c3a7502e6a32432be683b4498cdb978aecccbb30359b8ad107c3671ad1f721b9da2416e4e937824d086f489416ca53622e883afdf24597546f2a8736248dfa6a4ae4c20be1bdd1f548b620320c078d3e6f27d435ef2ca4b0b010c3065013c2da29f7f99cdb149a1786d255833a8dbbb18d052d54e2b4f6ce65266e3f6d9391eb9888dfdbf12a02aeb326395af73bfaa52e271fb7629283ab2784c7671a7208175b016110fba825d6d5389ebc829583aa3604d5fedcb22f6f25d73fd9252e714be3e19b888d920134c2f9126ba9aa6ed1534ada20591262d58c6c6df054963a12961fa6f3fda6efcf59ba6825a4cb5cdd888b9e464871e755516f2b053bdb53a060d0455d6b7a9537e4214b0809d6da466b24882954d12910cffb596e27e880bdc6a5dbe655ad6f5ca57238925de1fc31449ed312169624ab027094ac3cd32b2dd4010af4648ea7bb4c0d91168942e9bbdf3f3d15a7093240cff4177edf74f0a42be0ae43f6e3a989da68055aff8bab582d3e208dbda70e5cb83ce91c0319abd3e75bdc5e6bfc1a790b1274598cc34ddee8b8420308a91160a86b80db7b19868b827938783120c0b819a2812e7ac1f69611a78ebb95af812adc4e23e8f6e138376a4c994d0f74c5e5439a3ee41e5a899506920c40cfb6f9336b0a57542357ee3d598c27f68eb7727394e298d895610e947221cb647fa8733cbd5fbf50a62489c460ae974dc4b80143196eaa4d3c5b9a3d5a5827daf4a02db286bbe6bbaddddd3abcd36a8b0293758b41b1be1f3490958f35ffde4f746acdb63c931efc2ba42f0a794076ea9697c703fc774ded1537d670ade0d0391c303b573427ba2f2e0d8babcdb890bbbef25aed6528dd94ff78c3d03e31f908384a362ee2107f48c1a3b5f4b9e17f1bfbd65980c3274625ec265727fabe105730a5d86f094f9621276fd9ae54b7f099225612f030957cb7ea4e0f2b90c2f9524b86794fb899772d03c4c744dfe20aa84a91dd601bb5cd3320f1a439078a117ff0e6122117b24e2f2054080d0130dae5dea796db8f84c2ca14a2fff226f68d86d7d87ed3fb013dc29c7f6680daaae1ba40c83abd9618d6e358a15a63e017a59530b43550977f064903fe0b843140bc24a4d89613de82f5414cf40a095286efb5777f1544d9530e3a885101a40173ac61107dc1811092a0337520764f32340b8b9308c04b0252760d03c784f39780e43948612aad7f6e7cd57ee7802a35281d5ce672322c7389aa3bcbf04a14a19d7510c8f79281a509ec776236181fa6f47f6ba70a3116b7d99f3c146aeefe25f32cd594994d1194810c88ad29f55f48c768fe74c09d79dffd36d9ad784c1bea8acbbc82080cafca309c86c40860dbdbb72ac87d40cfbc4e2f9e1ea8af1ce15663d23eca712321aae80853e50dcded30bdb407b08d935b8c6d630e799cdbbbeecc422866258f2a5c11589c7af5c72f0b08ca5ce888c086fb969bd95849427f7734234ef9aa8eba10f21cd3011ff854f256ff13f21c7ba0eb97b772f73143cf7017304b5f662d9042a7c54f87a6a1f0890857d3224f9d4754ddb597693e906b7eb164ba6289b5745159c29dc22a163550b1d60f154f182d13e2be1afe60f7171d3e49a0d7fcaf88f805b9b6028cf8114b236d73ecedf60cf72e45b1875cffb6f3edaf963190993b0bfd3af1865f3e398c5b48ac480d501162b3c0e56d6ba0855c70cc48c5510e71c69db1e4273c3b4cef52e8d7d91ee26ea4ad0f6264c3f73c91823b7e54a8e37edab52e4d272c74636590aec683a5315e811a1711b9cc0ff3cf34f8100d904ff7497e807e1ffa7e6756d71810e9f8e1507881fed33d25c236f28cbf88ed20beaf4f15f28e34f513344a1d9c65895ecc96521e5b69652d986fb336a925a5d43f353693c6bb4ac33e83992c865d73d912061efee1a443e480d6a4e8c2ce072cd715fe5939bcf3fd6078fdcbfa5f2bc739e64edc7fc5a940bea20b0b9cbb7fdf111b13c9a813a0d5cb348636d3113a9faea4352981d93ada94ae8dbb1b885de8af6a93a913560d5333a4281df0593badc57ed5ae2d82c37f5ad7016ca770ecb4445b5643f54c2459336549e82926037e2b35c3f4a33b2c261515e29e2e4ae8afbebe4812694bd1582298cb78230b660b8fd4acb627b547789e733337790cbec1637a87a771d718381fecacfc770a6aae661728daa0b7e01bda51cd26000eb6d845b999bf319bfc573f0090c2b4d39bdf3d4c4415081c3130c913a09a69a9d563f0b7f648e0a987e28c34d7eb864391415cf2559a3a54eab2deae7a7023d537d68f16a00a1c2bd09413ddd41885e47ebaefdc8a81df30c25bebb5f555a8a96df0f8" - }, - { - "seed": "97a3d000affe93ef0b494aaea570ab4c7cbccbc4c69be25e5a0fe3b96eeab86d", - "pub": "0ce8e344e035970ef89cee79be3714a8eb0aea1a33967885587ad28536312ffdcc3ef886ce0e1ffe8ef21a1f583c8c32d5bddd3faa4d2422c92a684bfbe79e6a2864b3e73e8104bfce24a7a31a8666c05662be4afcb3e8f229a4da2c79c74989eb0bb918b3a0860b79f898464592450babf3b8c1e5361258f41e5eb713be887358f5340a4073df586ecf223549810dd514c1719486c6614a2d18046a272c45f09f2ac8811c94e28f821afda7c44bce9e9834c37cdce48436be5695bf8d28cc6b68b50e29fdecc9fed53a4e8e4c0726b42bc9c9644ed6d69905593418b2e4ee8af5f50b5d3be405b9858de1fb40c108fe04ca912d4ebc6d651ea94368474042938a1120bbc29e1a5d1e0d52793666fc83fa009f3d61c98385ca25975c78901ad5f1af98cf8694cabe0f44314c516eb49a6627683ebd44149a0474336318bc95108a2e1add7c8726e39f1e5afdfbd2ab2f4c13550c9d38d34b054e2fe0d5b00cfc1cb9745e35c6dba5a13be687ef1150a3e444ce820aec7ca0179259b9d41a69a3ac2f2ec8943c3f95cffbac60d34c38679879086a35b83a8c46c9562df963879343e2767bce70fed688755e8d042aa1fbbaa4989a0191f0620401ad1a03050598f3802c165027f7da27786114cfffc178489c2e52a39ba3605753f82fa22afb122c12db7874f22878be4ae617f132bd1a16aa9e9f424d07e3c1401685b11b013f91d89b465175537fd7dce150bcf709923bef83c8c65d18a5aa4db1e452d0a5a0c9b387130f777303c0c0eecfc44b3781ebe56d47f927e46505fef3e81e2503946d39de6a8b1e2c594b9c05f7f214e59a4d0d3518a9ac3381dee097d1f28165ed4366d04a72b1c743ec9f8bbdf57bb5451edbcfdc9f50066f3c3abf0e2557ecc55b0b2d00629940bdc2e621d08ba35954dcfaeb5a6ab931d2736deff44700be99b0bb58118fe26b1b20c82f24d262c53c597e658e0e87fd1c3dd2bbe62c0af9e39ff8c504aa08dd92a03385f27229de6049559425aadc0a64b9a459f2671ba2abff0393d3530bce1b64abda38c82d7f2610614d01486e16825e766d51ae9bc7e48a7574e7aafcbd1e7ef672c817aaf64cb173a6459032851271d8821bb828379b7a4c03f842c289ccea9f6913384f59313d0f8364b6f9d4480624481c39e304b4ae44383f7d3b646f5d761df88b32062c159e023ae810b04718f2de0eb3b723748bb8569e34c8d94dc41d2a2410c4ccdba42de6246f639c99b240757f0874cfeed9b15c47cfa93c6d4c8bb8b4035455e808853c268e4015564184417d44459eb0a4bd7e4e82aab7bfc5adb24d41b156cd95d0cde75b93703d1dab06a99be880851a49691f35b9006dc02f62cfbe0a5551e07bb03d1d290726c9ade5817ad83d92957ee6ac0c37d08da5b9437cd0d0295a59ee4666c57bb5d9674b408fee7377cdad3eb0c0301504f6703c70b69f5aea00927eac10f68ac50084bd02b713086fa95d1b0b35a08307dad5b896938638945ed221a2495b418c6fe4ac11aaf6b2e344e343f84019b562e6f8455aa39c7c2c34ee3ceb0f5302da58fd78d9031fe832069facf800dc86c3bd8d81fa8ccfd8384f3a892f4c9084b3663c763c0d06905d5bc30f932d57ba8a953699f968399a0c475545f6bf454440436120b8cfd156f8825cba411e81ffabfb983521627d59a050ab3846305139ae5ca5a321d899f972ef588346734f628468577cc802d717ab3cd329f2a74f2307ed87ee28e43e36b158a88189ed7bf23d9679a31f9f5a9c53f772ef7a14947bc3e6b2d1f28ac0e263c38dfe60dacf996cd8fe4b9736fcb7112a0c77c1445b53bcc61974bd05d63f0b39b94baf308d0f4395f2d844186270ab84c4fdd9aa63a9ccb6ed19820a06c5672286c74168ebc9ccdc5be384e37226a8b9c4a3484ac38ab44e586e8fde3c8059925575c3c57fe3a8eaa1964a8a7cb1ecd033226236e1f7a21343a2c2f7f13156501eced2c58663e96215be73c209b9b4d25ca310591ea250af4314e9b9c0870f1c373122d730cf799cfb250d1e03281ba4b6cb41a82cd458d5a02a96211a93156ff85f177d1efbc272d597e54220523dd1ecea067377c2a423c22003a24126ff32b3333994564badab496e907a84cb50ea140d8252bf77d1d540273c3f6a4dffae0564802dec022e121c984f873dd1c9a3f598d2aa9293b939ff48a77f1a29fc9ba3ce7f612174444fd327bd320d5d3530807032f61e05e2bf7ad94031f31e0ded1d41a30d0182c656c22d095ef492319b053563b57caa49ac08a40d0498e9a5f8e730c7c7d74faca270895f545b22ec2af5ad99fa944b7a44566160d83b98d50c21185ce220684e70dcbab38b15dfa184324b29997e3f57c46567c13b59c6bc6b7ea644c8955a638101a019ba238a801402c384893aedc48a16c0777a698ae22ed60dc7108df34c2e865fb4e17b7e32546529f90fb2c9155cf588cc9425ace517905c34d19f505a7c4ceec438bfcfe5deb285d8313c9745183036fe3095e39b04cc40bc9420aad3f4f86c7f7632f4fd42de5735c5bb29629db56c81ecb68c3c41ba84be5eb47e5bb9720b63ed52f69f7030c1dfbab191471f62f8bedc80f2a97eb98eec6d8d83a4f147d79549235b868fe6548f13d469648dfae9983aa2525f7d2ceb2964e79a7fb5e1eadd7584bb002e8aa5410c2374405ef6dbc78aa8f6e31f710f9c53f5a1c6113b03243fda10bf7e77078e3d0e6c384d44763ff780d8d9c9e84872af9e38aab3cd67fe13a0f74ba3e497d76dc18a6aa92534c552b793d7679d6e62af309835655756746770b720ec8a940647b47db94a75b6db53a8c5b9e6a182c7c40815bf4e8ebfa0efe586d1059e9c5292c8481c612391bd4887917ad463f8adc47fdb54ef8e241ee43286457e60895794f596a1617f1ea962960a11fbf847e370b9b8d11eec4dc9b0bd53a4b7af9cfd5d0b47c05095856d42634a37beb2182dbd4e0cc07e10d848829722ce5e2c204dbdb27541842bfcafa51e329d177bae4c2d9d4b66512a00c39bce2350e52304c4b4254991cc4f38e3e3689fd2e44af3c2d61d2b58af4f9d0aae4176caebcafbe732e641c5d6c3d6fd1414d7846c5111b3b22d76b0323bddf993ee12737d0273975db53fe6468b3c323454a56888bb08459b39be8071f354c1b4fcbb8081732200393c41751ab15674b8610557c3d30551aeb02ef6e6377c8786141e510f50056707a2506381bcd857e022548e84f71d0b797d0f7b33fe0978f570e4ac8c1486eed0762cb9c2c1c929b0d12c5b774c80ebeb12aa89b6c030ec0fbf8594a1de98c4d2f41410729892319fdb1049824f11f1610776508e86f173e4515683df2bb81728ee38d4f2444533646f78e3a6b9474365802d75d14ea0ade8b1428762c328e07cab71d3d849a91d68a34acbdd636483bc5f5a207a32dd3833af22b0391732afcf6a095ce00af1bf67b63f13bd3cf1b81cf6f8dc33b4c02707c398ebd1bd2cd1ccc8a3a30538979f8343577bd11e5a427818a21418d6d54d82a5093c8aa97f3cd70fc2c3d04883799331a8e5c9bca68a25624291fcbaeea7de15e3470034e3de3c02b94865c8181d5f783b2b03f2c603dd32f5daa6bfdfd5793c9f3b82912f5d2fba7a2a7d949a548aa3e34356", - "priv": "0ce8e344e035970ef89cee79be3714a8eb0aea1a33967885587ad28536312ffd84e7497c4845ab1f64b490973bca9a7dfd4b4ec9e0cd6740b7e7fcdd34a65746ecf01e135e76074c5f4e4c0b1ffb9aa4e5fb613143178a284b849707dfd6674bd36ad209cf9cf57e342af30e0844b54ce2fdbc4dfca55cf5dbd40d24e104027889022198064d4002905112258ca83052a64922a089021186e2b26064b62522b7294440489b125148200500c564144125d30446c1024a024990a240850b208d90203062102d11b70c5c328562c469d224698248818020911a3880a10402dc482da2320489146a2206290cb3882221299bc0045aa28504c08000332c4ca28512948912224420152d03c58919484590286c8c200ec03249431822039970a2228e81886da1c41140b42410c620023130022545091051081961942641020870e3b64c1b390d04070624119108858854a88049946994382a1a1065c1422908256412a22580086043a8909142925c844d04a551209588d9c6646442510b27500a4051a04024d026891803601a0960d818808b883110298409924809c9241983916206492285449290010a82601a48058012088cc04804a38850268a81448e8984910a85695b1200a2308d223830000229dc9044e0382023109003c58589088692801101a08103b00821a06c5a901109438a9a8031c2a809da88051306500b910924404094b24cdc889161904c5b4810a420601b480220a2490b802d99146ad498299a062c98466204c92112c28510b588c99290d4188690100d502464a3a40d84182c83246d5946700ab10140366e08938480b6501417918a0480d41000ca268918c20809428c8a809163a6011c1290081544e12086132852d9085052a04c0b912159a62d0a340a0b488e14094419109110160ea324490a252a0a3692dc2420133904c484255c8865e2b82000b184ca204e03b54c0bc964a1a60449366a4c044a10c850e1a800a1826549a008c8160acb406e181005ca260959902013284d9b8645109390e04689d4b210e3985024364d50143103979008235221855003a880184604db302c58086060a00401b22ce19400d3c430c0b22991c02d5416669330920b052801427263268209028e58026280880949b20c10c7711a02882232258a36329048669ac220d81642ca446651a46ddbc06c1a2812cc4602028924d022441909501b0171549490c89290420026e1885064b84dd98868a4263151b21019166a5a38810225891c210243387118950861846c222006a3302924b50908368408a26da4202d1a312da0b0645b96881b257013372ac9800cd412290b9311dc462a01146964002a1b1931da0208041829c3346ac2184e20148d9c485092147123973123c38921109120a3510819620b042a5940602490005110668c344d0ac42141a868008849214668623026c1c66990184a031442248364608865233861a29268d424514c186d623050020824e3384424a69103418d8c188a82864d8922280c23059b8228c9227100111002885162225254468a41c225e24690d4180a21484c81022c4cb8255c2249cb3069c93850d0080164840504432854b24c5b3480198284d0944424222e140922e2c62889262e9a400ec4444512304201c9680bb63001304948004584040ad9482d24932c99064ea3884989c88d5cc00cc1147220b7414c162249b809a2164c90121004b88c02010214482490442c194172211192e390704b004e0ca3300235810a058c62b024888261011220020665034640cc022cd1045203014418403024034260042259824160b80521a50cd4b86509396404251111c1708294900393241b848c084849a2a650240600112505a246400a129212236419483018454d5c26619bc8705124205c186e24a6451b1861183305829470ca0809a2182d8a44680a236ed2224293200d21100861341093824100402a18936414330013182d8c0232d32825e4904d00495292a40de11884129425a040815c46311191251a420661104564c0445b226509c87159260dc988658c22285c062563148058466dc3106662426624978522928054b045cb382411276e84c2215b868092400a22927141a68ce24684a202918ab2054c240dcc146e1b28281323814b1811d494601234241ab42894b208dc44309ca2101319055b064c10c05059304901908c9496686f08246c155b20ff41b010740a23ce4c3c107bec5770c3f9d9e5b51d4bbac195a28b7d63168119568bcaf7de67709c02b3b23aa56d2c9bfa84fefc6195c70bf33281c4c2db122f13abd5d79291f79da29a0cebfb3b0c91440b6a2f4f9ed1ee881b2b209ab7c0f93fae6b89c1978022980521277be844e9fe9b9c4dbf203d8b97ba7b3834f08d0dad171acb063cdde6099ee315e01348c76c0d2b0a377c6fa7d290027067a1200f7fc27bc95e5345888244a83dff4f380c621bfcae7035fa0f08c8caef2a71b9b6729d991ceffcffb9750c0c9296f23f2f0f3c26e860d852aca59c08c1ab44d3fbd700a3f5c7a9b33a9fe141828be04ce0f1040d6116baa2ee312c55cdf8f1195e1a590d091af95d0cc1bcbf775f8bfec69989773cfd29fa93aaed1da797afd5dd58f938f8ae8e5afdbeb331942a9427233694ae8f163911cec2f1ba034031efdfa21b0941c18c9f30e851b4288adae3c37e9023573ab56c4aad03d8f3084844276b0cb28c38b454569407bf58ec983d2cede6d0b9945d974b72a38cb0a16b27ea6a8c0ae72c53b4cb63629f536000d79108c4313ba99b20137b1b26523dc02f2c34cf0cfcada43584ff079b61ffbfd59d2409f53ddd643ac6d7bfda33a6801cb96f057d3dc55e6bf1b21c6143d784d5aa7d49cd03abadbc2d2b47c7558dfe88e7acf8f550d557ebefbeae68d731f651c859e35a55d254c7d8c2605de404fe94e8f461d01d2437b1a1f1201ba7aab0f19201751ced1d799eb6974e8125908a54f29524d60ec04ea6c91280e124eb255565da49597aef8d64bef2299b4289bb3950d1976f99d9f340668888a98df038669199db94377446d97f1d560e6a8951e1cf7a7440ab5c6f5c0efb15ce7bc0d955997c6351590190494fe30e30106b5af8bedd8563013b7967dfa6a6f341eac61e77746be39deb98ee8c4714d1b42edc254d4a522ef37110409350bbb26aa2da5457be77678d918722562179b0e79fc26439741fcc597dc22d3f578ad9ede4652884269759d17f22d0e03ce1a6e6e2d28690c2b4d572f04c27aedfce3ac24dc846cd0fa72eb06d70da2ae3992fa8cebd9798aa45a819acab9572b50a18dcb8c19fe6c17259c7a1c7e704a61de9c70d9317daf5bb16ed74eb3fade945520c733a40a4e7b2f97db29df0299c542aa419429f21981278510860b2a6a2588035822bb08ca57d10fbfc2c1dd1c202d0e2893cd273d79a774b34030763fd9f93dbccef3cf15401fed507738afff7fc1a0b553b4bafa97441710b7c36bc0503173a219cc8babec31f9b4f1cd8b09eb230c22a538718e66a9df4627088634bb26e1bdf917b2513a3d18c129a8efa2d569afe672c30c1bfc5e9aa707ca0e7b15bc5827b1a8ed263f96a919d249b8c1fd8dd30009a739e3d7388c3c2e4e66230d0a11eed2ddc2e3b3a423effccb0fcf15e11e2a597e17d09fe765b77fd1d3949c994661fec8228bb98558999b48819729fe5445a53300d926a3ff99d3494ec58802a955242f081cdfc0351e1e9b19026613249952bde36a86b2d8c66a91a77a9a20a602413aa8ebdf0b0df1cfbfa4a3fc2486d0f1caae147d0bb2a821fe04f7436be49b20f3d47b3b1ff1b18c7b08fc3e357ff1371f54145f333fedb7a320d49a2daa6a8c5343e9ba0b9d5551360b2b81b50e4336da72b95ebeedec8abc2e36f3828b82c2c544b530ece9a007a3225fc0bdef490b82b456c31ca28ce5e3a2ee5cdf55c82a5aaf8f1597d7f0ecad39e64c2241a6d9077a793cdc76e984a0b90f3e6f31a63990ee18f3bb9f9ec58cf04f1bf3fd2b15e539f8a90fdd26841eca75dfbb2eab111fb8a0fc6abfdfa1dd3e9b7d826f9e83c89f5a372342d13e264e220549a227dc7d4ebfac023c81a633aa0908c7018b46384a440fa3a1a10c7f50b1af580b68e83ae3e378b1c59038a77854a4b9bef003cbb89759ca8c398a17e009ddc369a4026e8007d9067d9bb096ec81054e1edd13fed4d0b4f2cfa8861bf0b12cd41c05c91d3ea5927818e3a8b0f619afad20f36748e42c7e596ea85eb391aa5992510a16d4f950a31e319df6fc04edc9590bd90c4ceb3b3912c787f8e289edd7d6bb2535d120e007efebdbea7e6af7f0e108b1ca4ffa43b396ac2af11ffdd3bc353a0aa9b0a3d764dfbeb418a125be4c73c6704d5459cd5efe0d661915c89ce07562d991abc51f184873140c76c7032d11db07ec54152fe9c19196b45e2f87dcf7bc98daa31a36658542903ef5e1e5be25f09257ef441bd1fb1a1e75e4dec96c36985f0208a17c52a85dd35e01102d6cbed02a099f66c02049397fe239ef1fae37f7baeed6affc3e97eefebd911c26b0cb36e17cc3e9d75cb13081ce50381c0bae7924d9a0bccb578eb58481a60baf9cd7ff979f9bb0896b39a79915699ce4f81309078e8864d820faf0e3178de0053a15ff5d5c8f9cb2a2516ec8d0f16968f5ee8f3a8be7db5ee4fc3e1b13702706e4abb75ca419ae399900735df9a2be1e2e9d666cd09da40bfb3730cc30c3a84da761c89e6226314294d5a49c1a6ef147ff8e849da3b6ef5c9fc6e80c22ada78b83209f0b668f04616a8db48c6939a70bd0890e019b65c5662fd3f4f1f212cc5a27af020a61c2c54c6ed2ef8ae73cebc31d1e808669c99fabad22630e246292bd9041cc3defdfc649f3140e6074e195719e5e6a8fc5acb4dc3b319dea9eadc6219cb05b90a1553dcbe7c091d3e4e76f722a5356e33a5a5f898ff077137a9334673f17efc5b4de66314f770c3c854e4c2727bd11e5e15b68a8fd01f0bb42fa82895593ceda687a42dba6a6276604a26ea59bcb45d96e6df28cd4c99da97077d3b50a4c9e65104662622bf964879f5c200f423c6d45764a01ecd5aae3f7cea5b7173f11390535e153dbde3915d289b8bada96370e24796fcd6f8eb275beecee4e76d2435136ec2b133d6ed2410f004e802573c4473789a22e7883830dddc590aee33e9f7ee6746c89683d93f508fce0916d1786163a90379d6dcdbdc94a0517976477757edfb1463158ee9cf066ce3501b50f284877db8a01fab6b2825aa08da193526af575bfe995976921dd61fd51de36a6bc260cd0390d1e48b4a0d62ad5cc21e374ab061e863ec6413816f6a91ae91e5575c9d9f42bf96cea4bc4c80fdbafa61fa6170675c6b92d9b44846078f6d4cbbd108316f35a4eb0caf469c971405ea0040fd7f23539a7a89961085a70c0795e5e8a17af5881c37aabd0bfa81c7c86937dfc78218ad1c9c58847018c37a2f8983099cab91f88370e65ed9fe409a6a457576f0c06ab1f852d84ab88f8b24a7095a408d8d7c85d1e9e9ab488b5382910c7e8c6eca29e313ec85540d7334cd2336f7f5e1776cdbe58c5e489cae6e8813b6b9c7b96646429d8e1b3917529450ee35a4bd130a8f5e828bbd11929bea2fbff44c306d2ee069bdb309a398de1e6557fa1d6eebdbfba1229cd749daa18c9ec6202b56912ae445e0896e36ae53020275c1c2d76405eb91d6beece4a2fe353798b1c3a797526b948ea600b2aa1d515a074155d75c9f720df6a303ac6c2274d2bb6f82224c463dac481116c44444ac031b23e132f20c8184fb758102edccc6c323a55c867214d89423fb271d9e97b6cbe653445c7561af4b8c01aed322ebbc6086fd492b812748f08cfdd47578eac864ec54de52c2e0be5b0bb01ed9442aea38184f0192cbaa59f58663490ab0d119cb64bb862486e2f5c4a41ebbe69cd263636058b971a3a043abd9c902e897e8dc0ae651d5a9a5514dbef5ad37b49361a3b18f60d833882d3918f1bbf910527656eb185ee6d49800369ff1a5149c011b8cbdaa2aeee7e298e72c1682800d30fa5befe80dfffd537ba2b537ff33ebb4176a8d650313bcbce5a9b04c49645b67edb11f4b9cfec90b07e7e854c4127cc49d469e18823584b2021c4d06d17f404f38cfaa251c9082e8b86bfbcd68a563f067ead1c7364bf1b80de75d4ececf3396e80925f3bb713a26d871d32bfeae17ba1ee99239408b2aebafbf44e66ce08ca9e7b0e3d16d3574e6a624fe8fff1363299c3c7e6e0e6a660c67689028e7d074f2d30d39ab18aaf2136248dbc3d61a148b9d0b4c29dd8e07cdd6c7b5a8b06af8f0b8d75f6ee3fc96ce46c3e46e3054f41b7899a28d9bb68f39dd03d0184fab768921415791cdbbf86472f522d973c96b78a9f3501437b0e6ce87070a08433516781b09c74a7c3e2298cb9684dc91d6cfe74e87c48973831e64eb14496819b5f7b1c028c521c9eb5ba3d7e1de08bec11183f2be297cf15b89e1573f0cfec1dfd4095b463cd2f83df28daae1ea76901ceaf335f59bfb4fc106c67969f5c2ad9f7f158eb807287da6e4eb31ebc00bc951d910b22b3bf5a5aca93ce73e23049b3668706afc4b4ec703d3179f4b17172cee9b80e6c793d057b514952feddbb2dac74b9189175f7a94af4abb8e67212e6d850fa5f90ee5c39f534d77de8da5ac20924e71ab2ccf409473e74c4d7775234d8c646e0077b82afb52dc8b63225479d0ac883ccab95d87899eee7f5ace64f67a3293d09ef722205925c1e11a115a3cd8450a78da5efce78f7845bc7a895d823f8b27f99517c8f54c4ffa06d459dd0d160451de6eb4e3c0266dd9dba4d8b354a0e15a83704fb143c53519a3f6d3699ede3ac1e97671048cb1e0afa88f22a8a0cf14e2c4f4ca03e2f023" - }, - { - "seed": "7ec2db8ef44942b337224bd2f89856969c0896fe2de48a182888f0c9a3f02935", - "pub": "d543114bc09d6cc07bac6a22b472feee6bd3ccc4f3d173ca054505e314e0560f9950540773aeefe2d4e062b45e786794809e38ffb4e4eb0725036eceb5ffd5c6882f8270b84e97bd012c43f71deb79696be2d9824f86aacfa171e7cd7d2fbc5d46cc8768705ded4dcc5b6651316801b1089addab02bbc8d8f893f3806d741944ee27d7f4badfb1d196c0a0b7bb117700a1c8389ea2f173fcb44209498982cdb3c18b7cf2ea3becbfc1ddb886bc5f18b4a51a3946488c2d5680aec3f8736deb18bd6eb440d40527f53bbef11fb714da72459da6c12a077481ff7bc7fb50f88da3fa35906c1099986644399530bbd9423ba9bb2d44c8ed7c23bdaf6e60db0e8122655076c47be042cf8b4eeea7b67de5c54137f9273792c3bfc67763776df554633aeede2a4d94c004169cf501b0921a1486f5baed906393152b4006b921fdb3f4e8260ac1cb2325748eb987a069a2c2b49907b1c1ecfe066eb65008a4c2a1a0e48335feafea39f85d1f86a25247b9ba7a3c480e2de06492db70f4ef167fd0ababc4ff7d8570d1e0a59abd850889a9e34d43d6835caf8c10f6aa7529bdab886001bbe2f3cca7ab4af794bd545da6aac5b823873ecd3ad37b9f9d237fb190fb2aa009d6af9aa117d70773f425c9b1d03676a2bb8e020f51867aefc34a0019f9b2fbab01be9e707cb57e1c6fd18201b5f3838bffd93af4e12c73b584824732f4b86465adbf834fc1cf829542c10aacee3dde5ceec9ba1dbea3fd4c83ac194a361f97e6e87a77a115fb8e4e1404747166f7b1523eb6ca3eab850dbfdacae8641e3f41254de013eee2d774811fb508f8e7e7f82829ed60452fffda6fc535901df632fb6fe0a0a4fc16f35cab61a7c3945b6ca7f6259220294bd12385468a1179e42a23ac9ec519df4573fc82cc709bc99313c8027c17f1fc36307fc397b18d89a60dc1fdd4e87ffd5026d2992816de65261f44543ecc235c4c2caa7f1f02efa6144bf4e3352af8c62953810b81deccd56c27dcb14d8cf7bb429cb2bb1d45b861ed7504e496095699ac1912d37f0bd33a678c8b7467c4be0d07d2313cd7faf9ccf2fc50309e26c4d9cefc732dfc4671f63eee0e4b1c9a4bf06a907f633699bcad888de566efcad289a229f630a1bf63940adb110d799b9c239542c53394dda312f9f6a9cc96f784177ce2b9db241d475eb7e06b5e2e37f194e53c3f114e6d2eb45c0ec3c3095513451d9cf588a3cd05d8998f903750a1c4e028e4796b9d5e5453a0f072bbe515a737a86898f2ea14407259ce39a84855c6acfc4796638943bfc6be0d4b84edeb5333ab89c440fa39878effea1aa4c46d5344767f7818543f5018dcc7e8a0792f50e7fe7f7b6544146cc3312c246d950d47972af48837edea6c1271041839c49455ba9a202ac589a9e526494aac3248f3d28ed32f3ee36b4dc9546718cb58fd527589254f349be8298c94d734b97715972fa8f0d20a5baf5c03620d4c87f5c1c91ebe406c334a1942a47df4b733faa2f81037f8c3c304bd84e86e4d7fd51539303c8cb90d6a813df81db8faf351ea046f448f2838ec5029af05b96c53c92d40ace685c6da1b3d655e24e04dab9ce7d017e087709ab9bf934b74400255451bd7c0f40f6c7f45971b6d09ee54a3ac7a557a57697dd050e82222aabc5845d24d0f2b980ddf8ab4beaea9cac6972216d5d31ab4846f7f5b1f91377d5ae977f839983d7f46467580135ba5d6254f51df426df4f01eaff14f9f129cc35a09584249036cca42d53c05cffde0785de5c82efe47fb22f2b5583b2ef5470f1b9403c99a2af0c3429313928d2f2eca2672559657ef4b16cc32177e5b0daee1ab40d80fdb349316e92c8c788ca3e8c189b7be11204b6cd1d9ec82375dd9adb7ab77c9ffc169bc0f1c9c0e5fdb9f422e02fea02c0c587ed586a9d4b22394f72fc7fcb4547cefc448672713c59268cea8f8b477d1eb9f450b75d49f7d55ebd6875836e9c0f16fbb6507a859d3b56aa4afee6c2906796a50e866a92076b3addf852fa10a70b6e0a6656a75e23d06a33e0bb987418503b9ed364d128261a37389a1d30635d2212de42ce8da273d122f886313609d41f816ef040daca96f8bf06a6a957fc46934ba973e730f2982a35554ae13d2a371682f195772f8727567dfc51ab8cad7235f706473b7cb404af75fbd442fb6f40298732432710411a712ab4a484bfa30cb0f303f01e7d3ad503cd919cda0c26d1d6709711262b3598875898ed7222fcaf0891093fa9346cd630450ab61e7780ce5412a850f59c24b96a6eeb10da67d1e035a790009938168a4cfd2e2a8cb313cf04adc913aa372b20514348f37ecbf42202fb7c2da94e78bcc257e7e2804f36f910ab877ad94834b3fad37533897daab1882c75c4fbd8a974061359a1d608efeea0a5d5dd0b13ae652eb61b24182d30ae6c8d57380d6631a56a1f834298ab59c03e836bb74daa03b31ce3b41b51d45b410ca113466cdad11c7381ab2101009571bd7f059ebdbe2e767507d5468b395c8d03f15a6bd89b689089927f6b269cd612f3e5c608d3b73ae0cbc90c6b07762645ed06f3612049fba9d38663d2e8d8014efb549a4b8c5515b889c41377b154be541a3ec35e106de5275c423f01dd14dfb45424f08176931e6cb8392e06cb7941433d3e1b90e7044d61f314324df1a811c7bc2ee47518a3056c2d8d910cfbed67da20a557e350b071f5be9d73f6c24a595c83cb992b687f184f8daeab8a15f3396bd614d6d4831f07e46aa6af35d6c712b96aa4674f074b68d4ea0cdfaf8e1a1241f748fa9aec11c9d0ae596d5c8f8016ec2354c0f3a462bdfeb8534d7e779ea64efc73871cef6fa4491fa0cbf7d196bfcb2dad386bfa090ea95a0e082ea905b2f0601988fd5ae2e2f155f5a1bae3e8ce9b7f0fde43b0990b87e88c10147cff93d3defda18b9fe4d512e190ebfbaa8000e561e205aecac1fa4ac39f38e79ca944417a09244c79cd015e076ea1db88f639e60d6e1ac8fb03367f16a08940a9487773a3944c0e9e8ceb46b4fa1d24dbe73b05d5cb0758a259ecc865f9613396641a5ec9a829a760040a68651ef3a0c0dfe8a871a7cfec2a9822b91ced526b80c2794684a15e57333758c80540e61b72678d1c437d0724d7134062dec7efead2073e7cf7f9598bac3a40451cfbf4a7688967ba424fad7063ea71eb74be76582206c9029bc9c65ef9423768ae578a732adeaca111bb2cc32e24144600cb3308620166aa99fa88032c3c3036f530ca97ce426238e65d0d04e59a851e766bdb5e7bc2b98460cb3ae11ff9852f2c58df76af267b1d4e944473a0f7d4029fbe65d789dde0fc2657cfdbc2d07b3fb8e639ecd36d9cf1ed3ffa7c423dcf60139468d38b541c40ab9a2a3efd95e57764f34d0190e80b996484264f4fa806e8db709ed90671811a63b617303915c270f642aa40cc8988885ad980afd68124d1e8e24a9d742a3eb49f29e4767d39c5e9399df141a26fbb8bbb4e0f53562b985b4abd57a3043054a90d847593360562f2ba18a292f3ff92cf34976c6f35ba6ec8317b99bf074b1a05581226ca7ebfe11294de49f6037b33e77a0463e0e73c660a81f16377cf3847ff7729d5b860027ed06623e22fb6cdbe0adc8d33db0816b6edfa2c3027413dbd3fb", - "priv": "d543114bc09d6cc07bac6a22b472feee6bd3ccc4f3d173ca054505e314e0560fc09b3f854de2aa8d51e767f9ebf663f41ca13532e7669c5beb64aa145a809d47c77b754ec5cd629ca21ba82aea4676f7aca89006907ad661a17bdafcd95505aeaa59bbd157b689567699f9cd0ddf831a627f5667c0d06bdaa6f41ea538098b3299c241112572148324db464e42a00801a50502499099366c5cb2315c348ca00401a1382c53108c12212ccb008482042e62224c1c07309a840488346a24c9404c442524350d8c9880a3900580223280284412b3915130211b83801b348c631081ca8671d8b26d0120421ca430a0804992b20c90c64c12440e1237056040024a26285a288221338091c030a0a0711c476184c6711923621287810934680328458c869004c830dc204e0a483088104961060dc2162a00888562a260084725c8b20c022265c0282a54168219a03050100adb2448914631819885c4864c49242e23b048e2060d58801049b404cb444841c6916386204224104b848593986590029012b88101b470002390891292d3822510a810d19209d3c66d0b20640318310a2740a3b609020291030605d89201083890da880ce2306ec002404220009ab20811c60cd846880084490810888b982024c46d1b464261264d1c122a1a2646218281434032a2b80d1a252d13930080266c1b08401094041290208c1028c19884d9303204028e14930562c8108b32704b126153162d8b166601c00c18388e1a202d14a84413178d59028813b2051b188522163298104192a8700b332ee324461390812239650007461436808b024623c765c098019a2821e4b45002b17158346c0b340c48b48c1bb02503a670d13871ca107002c7081b293123362298841001a88c90266123a78408b77018916114b16d9a228c0b4324c816524248281a90884a148653282612482c12c6254c8844da36659c22641b004902b95111240ed3362e82160420082a13c28013c80c4b8444000230c284606048069a981082301084306662884c13380a12328c14347284266e81c64c0cb90dc184710c103114b32d44466ee4182d01086e1cc4410c418ecc444cd1c68948161061c408808888c288090ba1918934051a336c189588c904714832625c364a00158160368c2043681b842d1a8928199348131301c2b88d643224dc9009d188611934029124015c0041098240a24600581685c8c88081024d61c40580440d5b866d01264a0ca1200cc910014885ca0284994890510611431460e0a0612017055b942d630631da906980a049533801e4062900330aa20248d3006161b8452388018c9800549440da106d42489061c04d62266841240c09234ca1248cd1387221a12018439049148284442860a68924346a09c22c94024819934c241992c9081120310249327203932104162804102123c90149828510b98d4b980501026e1107311ab4285ab8499c48708ac244002242c2028661148612378112931019032aa44466a2a288e1460c24452ea0c845c30826c4268153160ec3a28880946051a2050315008c202582c21162128111996551102418884022042c1ab12452947063a08c192281d1968d8386402484608848520c008213b2880b330852320c20a10c9b006e24878998444a01026619a04d11138d0c0952900468ca4841c91260d4088602c690e0c89161103040966401462a8a002464b629201266c28849604060981662d3342620c44449468151325118c9244138288206509c22320ab94d22230c0b0469d4b4104a004a0c4766c4c60540a46410890ce14828c4a68ccca2085a4052118371602089a1189009432c5882459116615212609446706230094a9051139910cc024c0ca85090a24d022986d292909c2229199801c0b050142789e4a689e2b230e0940902060d84a4681bb228d8423219189088046148002622132a234332a3a445130624a1826402420a13315203a228a3086a4ac00521847122364e9c128608170a23110c9b84801c386999086200198dcb08245a18244a063010332200a050924225c0326d83243209103011454020c4881b2361c3424c084648193308201168d3088d12033122135099282560c629512229514046a2468509118523a32822b99192388dc3227259b801e1001109c760e118825c8084209945c4268ca00849203452c3921048124c9120455b29c22e5d4f34334a8b0987c9a61fb041e410adefd6f0692ecf6b2ac423480ab381f022b3d3d7fcf27d32a5586d3b57a2a2acde364f32f230dda3ad25eb0de09921979bf24ad9f1ad41ed613abcba35b9e607193769d10cc06b021f426122f5f9a5086b4093241fb4f9d20523476699159d1057535cbb18b481c17a337ca10024bd243a83bf3c9c216da887bfeb4269a316be20ad7e626337bf00059441adf9264409f3e07f262ea248f96e57ee8dfe13f2ea1066258459c3a92ff16f303da60ed9bdcc6e28aa0700be10f39b0bd18bb8f83e3e5695d215e64d72e3e211fc89d354553163048628d74638916b6dcddaa345c02f861d48499402e71c2335fd2c13a3b97b475b10dcb90c93244d4c2104cdcfbcdcc001d5a7be41c356e8597480b8e6ab20c26f6a53c917e918a46d88134cfa41732542a75abc51fc8f9442c2f8331bf9d5ff59010f4a02be1e65021546a8010bf27d8223501471f987d987af1c02cd1d99fd8068b3065c1a1600a27e074dc04bb44ec328a1f529824b2b81769dae7fb3f9a155eaf985ad1be1631caf8065820380c5251a9d8054443e81f12e4c765d85c12cd49d6d5c0a97ea8955382b064547def30a3e71ce5ffdce2567003b389cc1fbb0dded85ded13211ac8c4362de9a1d7ca1f052dba6827045cda90d3de8f0ec7072efe5c903112ddde9c0a3e189edae898e8ab328cf9b9acc870a09fe9c854901b682eda0e32c05fa9f976c62e6228641b2aa2ada07f8d199e62908a91428f626e58c31b894d72e93f978f5087ba9f16651f31a369aa3ca2d7a70032aa649fa2d0a009a166cf34b1e5768c3a02a7f6fce9050c62016e200783ef27c05485c4c59105fe0303f84dfe623ddf2c93e49ef8c340bb8118c527ada143e67c40084acf637cff368dee239c0d7fa01281b8aad4804ddb757057d27975d3e695f1de08e7443b85141a5ede601ff4a877d7da636162e27c8f95d535ea6ca5e88e02e8102d8acf59d01cbcf1288ecb80c8eef914ccd768851b8f395abd82748f632e7cfd6248a2096ea874ff8da9b05badbdec277461bf41a4f3731de04eff0afadc94d08b3593424a2dbdc016f4e3fd313ffe6a0eb5e7d995cef61fb5940cef3663d47a7dab348314d9401bd34c76fa73ce12f644db4ada0834267f3ced7ef8e8c2567e039236f0e7365b0e5b70379b6bfb69bf20e1215f539c97b78341ed8be838c51b6d8debdf0ccaaf8de21c8da25e1b4750fee7a9c811b85a7047db3a01ea549753571823a41ceb0684a30c254542b4345e4058add41f09ae352a442d665f54e8fb62e1cf1f4b2e90a7e17fc65e2d6fe3e4944413d06e91cd086a509b5b33a7ffd5bb2f8e67bfa92e8622092683cce1e9b7e42fedf9160e6b64879edba69152678934bf8457472a491027886fc1b8b66d9417c36947c1ac5e7aa86892d3a6f974ccb1d88a175289965b9a010fd26cd8f55c3af0cdbe324e8404129fcd4c8104c48944120eb89399d8e5e69e08949edc79e65ac8a6abbda667dde3654bcf61e164cc38aedabccb5f44c6f1d1ef4a86facb5333af91e7273960394fee64e6c49fbb70c0870ca72f8ff3f902dc1af05d19accfa3aed66ff42a5c6cb0c24b2c23bb219f9f0088bf3aaab578342b40d11203a651b34637dd11651ec35a7143c8ed8e753dae78bcd131f65a23a4202da14ebdd2c9802745e372571030190bbd7f869adb85995acebf16b6d3b4570aa66d6696518d25817fac06ebc1d2135e808540f3671d12af6bffd792ce16e3593546145624fbe42add66922abf648b12f6446bb1234e0bc6805fe5868806d50147a15c912cbe44b1fe3b1d94fa6c546302005bce6560c5c539919217beed04e534465a203ff04a591e1f88bfb1a086b03db3ea34b5fca2fed2b2ca55dc0b2aba5e74c3ec60bc09cbe9ba2995935c9c442d67aad2f0cc415e73cdf9f0b913fdcc59ad9b9195b6746755f2caa565cf7a4187066651f5d97adb4d3c164f42bd7ee9af1203f472cc7ec8ed47817538c7d762a74e13557f8b7975e8892a78a3897d10fd94e66539793c6f31cdde25aba77b0c9746df77519de39719c9e46ccb1a7c3c83528c32b326a9cdcd394f4ad326c7629cc211503f55e9d7a4ac40b6850b21c0d6a3e773fd156f4c1d032b6ff22fdf461d744f32b2701da8a32621db7536af92e03245d3b7f8906777178cd8c747b06502228d126d30c68d8453484895047561fcf78cc1fca1f617429e55badcced5ba5905b8c43b62f9416dc929cfac778e00da0c9d3e3431a773732c8e095636c3b6b88719f258be65ee10a827fb2628a66cff9bcbe0e648d66fd8da200ee4a6547e367434bf8c36f3fcf13b1a4557165effe016f2bdc3d1e6227a59b9406f69c28a7c65a8a7d6ef0cba1cbe4e31b50e97100a144af06d22dce8125366076a826c6660faf8ee6d6f1e10c73244c4dfa78064a1722f261568559532de18177d735f1e04a60a68293bba7216c30d4e0db3939c0c565bba8ebc9c6a9e4bd0f064b79c12ddb938a0f39c2c9a6cb42efed22fec3035340bf2fd5a7994b4bc2c7455d8ce03a4a551ace9e10e96df8d66baca31de59e7062fe2546fca9eb08af9b0af2b93a10780207a6dfad193da67fbc94181ce012db16fee63c2d16a93d37ad8edbd691c8d675b016ccb099f8df464a011d48896fcf7eb78e5ea3d1f9a112f30609ff4b3b217b791c574ed05b1bc3b1a4a1873a4b5c63ed1401c3ac8683fddf935cfcbe2b3c60a31b0caffcca1af045e7078289dda4b896a8a2f5758b780f0454162a5dae714d8df5ed2f46fe076a567c5fdbebdf2cb2da5ea39c44f410b936af178c848c9344d64cb7dc005d6229ff47b6c0c963eb7fc7d03f234b81f04a944c014edf81f60d9fb6f35c7789d2d29958b1206fc8580c04db7471c54c87da9ca45608f152aaee2fcb135f52e5dca2d7c0aa3efe27a87b63240f4c18dfb06af3100576cb18cfd525fb60aed604e40dc8db3db1fb35744d6d2f1defc947ad9d50633e2a72c7100368e5568ad06da121e56050629097703d92f12e5eabbe811725462bb8d30691e1fa39c8d74654d089862d333582d0767cce12debd0d15ba462639d376aa657142c7aee6d330077118ca33d12b165a58e9c575218b17846fa78b450c3510038014dfef1f6cea22d590090569787d8bcaa9589d58b4e4149ec2de0b0bcb4b03ec8447be2e62f312226ac369ede92ac75e6466a711ac713e159e34a29372684529514f238bc3fdd1e4cf71ad2b6d0b32a2cbaa5e0374c3353e4437b02c053f7dd9f5ebe193621a49fea338be4c7946ebb71c78a77472e12c7f244c7af778f3072901483cdc1250f6e39d28fcde13afef553fe54814c0bb66c9aaa383d4b8f35a7ef4bd60a1c2583f588a8110650da7afd7a5c379f4533e46f8424dad452f29edf50c85977d31668199627d1c2e2098c731bd42e28c2c4795e21dde8e9e81ce15f62b8eadf95a33e5367c5805bea2a063bea443d7f53c00a91d304eff64d99ebfee4c59d3c7a2351c56006bc1970e917ff72c196a8cb05560d6c5a3b6648385e8405b6dbc1b95973b3f1cf64a1f410a6425362646c1eafcb4549686c5a53fbb4f3699776a162e35a47f1cc3ffc14f837d01a79b11df1bd02547632e67d605789083a6ff6070d5f7b41c8e7b1f015ac54daccca6bde4ae1bb39d2052bbad2cec45471c7b7ba79c2e51c997b2ff5e9128a1c6978715e9e51d44ce316d0139665e4bd30ffb35be87784c061c91ab0dcbdf6c9a27ec3760eaade5a87123f407824849beb84ce995f9428e3f7da987a4418afd8acecb26228bd0d4c4b48fcdb401d287dc6159a08a5f79c194c65b0050d09680080d5f44f32bf85abac2652cb2f87588a01d8fe503c487c0320f6ec09f7c490bf291367c7397ac5cc92da8a60fc33806052b819e6910fdade4f8873b442b571a05a9764e1071039df6305870235e8de0a737f262ce1f9431d3c37b605247f59a7483eb6afc58a70d6c5a1123d5416a8b2dcd70698971f93ac3a4baa97bc841a1c91ff34f8a6fbc123f17ae78416138e7f552f16afcec497ae8ebaa2370bfe9f88ff7a3df8d0e4d34cea5a5cc8ec45d3aa1eb61e3d1d67624e8088a3983a67c9a10a9517de33523bb05ae5eb7c4d57cd21ebd1217bd59d4b9bf07ff9f3547551b03c8d30e37a0bc3e67f8a455e0b1c8241bbd77d2f9f55637496e98429f1d99da58a3957f537b6b5245e89f452a49bd37214c56733c2e244a43596483b60a3b3511e44d5b02d0edc330b20f32ce7a0a73d1c7558c9d47ff3fd99fc391bf71121edabf6c14a0562e3b8d19083cd5fd2b9df0c8c96946c552f14ba57fc4a18434649765f180a59be64971a6979a3bcfbd78e32d8f745687d95bb7e4f1f8f3830e7f1b0c7ca3594c350873dfcce3611579965bfa124383653ac5fcd36265dd9c56dfd43834fca280bbaf95129cc9c0b2795b00710c20112bfc50647c0b300218e4d2813578b8f4063290f40cbe26bcb054d7bdc11697574ed0a718e73ccc01cac38825e4e0ed3e7f7d8bca516c08deb620c0fb8fd528f5dfa7accd5eaa9c09ac12ec52ced63412d90b383fdff0068b35229e0b7a44e13847e88657cc4b547edcaef9410e65cd9da885f8e852d3f953e90b1f94e09bedb49e4cd2ae70c28ec4965d4afabf2081085db5b7210c75fab80846d751c086" - }, - { - "seed": "721cf4bbe67913fecac2288a697b671b84e1978374b1f9715697df5d6c206d53", - "pub": "0c7c3958d1691c75ec7af62d488b1b252067fc298b75656c87608bb94ce9b35b8fd6032614f170494a0c27873ec5e98a3cfeeb19d0da83dfccd94c6cd0f90be7924232d7bd4ffbe4a0f7cffb1a8589229a473b7194511ebb1ae81ab5200b5c05e36f1568a886e466902d34fe02b5897a9b517030bbf11ac35c25dd233db7d603b83ebe680444895331d1e4ddb83471cc0f61727e40701e7d7ad71d49a9f080e257635628eb3ce34bcd87ab69fff6b31354b1793c571cb3d3005d52593261948ce80c82f2e685981fe4e66f6532aca8136cc30a5e216c8d6b6c9c0ae6922d65a84648a52a313dc9b20e771eb6ec608a18a53601882528a4bed2dfa875a59614c9cf7a751e2118149acd03422fc480e68518692f7db6c97bc5d4c2d74e7eb516bb6c40b16cf569fd5325c08f3ce86f68b7df8c2dfd7de437f285d7e987eca6bf2e9811da7de7f038ab4cf89cf01c55d1b00e4655fb174e60af280ce10c68bfd6d5ac98aa556e90bb68ccda5937496ff636769a075d5e651b1e0b529e65f7406b152d83da7d772542d0046830f9580d2d5dead5caf309ae9fe73b6d15a75969df5005a9772ccddd69fbbcd631dfd9e12f71ac28f9b7d9ddeb62c1e342726d6d9c930aa28c2a9ee0ab858b5d14c11b02f9c1da74f55de992aee9e6f62faf2e818dfd9f0757bd7e43f3ca34c75110e63a23caeecbc000b8ef63857ade0ddc69b05a678e203e742e5741e8544a729bb858b73e12fbdb4ad973d3b9dcc1c7b89446776e7102baf4852bce8d10acf7e83b723f642e5c5c02ce5a363b0dd7d2169b4176090934cbd08ee05806a073b362564a65a6c6ac91c0201d382592af115a09eef88850584e77fef817086663d9cdff909b4ee11d3a5699fbaae371c5586eab8464e916a7a0446bc0028a76113f3e0f53bc921e30d0666acf2268a705f7ca57f774658613f7f292aeee9bbd92ca80f3339915fbf13e8b9fbe8cab8385c8aee1dc1ef604d64e8078d7ce57bcc973da38c9222f7bd5dcb8a616caa88568888afc0e4959af5194ac12e63ad338c78f046751094dd70d618efac84d9a38839200005347fdb624b5f6c42c53c75b660cdf4a809f2ffd7b92f3048d578e2acd97f3ee7a549e3c485b8e6134c712d84d05cc02ecd3bbd2eb764f03bc1200a0347dc1ac5807230e51cc8e745e9bc8d0f982b1d4824098cf6ceb09aa52363b30704cf426469e039526d86684706cf95c7b737423d9f768ed1723516ee163100c141d2418f1f45d9e17ce5cd107f014eb9c4de4345d6a7b063176157e4ab8f1257113ab46d51da2a123312172787c8da275d39f786318fc0ce2f32ad61a80f8fd7d6e1b49e428633f30b221bc54e5850c0b87151262d83de2bd21a2c6ef0589da1babced2f9147ed2679ce7f9e9029def6ebf9a644fb2b059e898b7fcd3ce4a4f760c2caa3f7a3ae5aba97199d7620618ab8b45b827f0b5dcc9f10a7e20d4a0a0d0c26e46bc160b9bc35852ac93cd7f67b1380fd59b38bf8dcb1673a96d242cebf9ff3c6e239f341b64e4e8dea799a2795a1ff720de99bf028ccd615f050deaf17707fe592a81b7e593fa987a8fcb2623e71edfeaecf85e3408588265f1657ef89ba5140bd710aaee3b8eb2606392418c364328e0a373ceed1eda547daa7311e5d0b86e23a0f46e33ac12b4ddea3ea72e64c9dede27aaac3ea69c7ec9bbe6f807a17b58199b996a2e17ffd75a2b4ebe3d882d95f7979c01b7eebacee12fb3f17491c8fc5b17e08dfe9a10a45ce0f777ec85fa088c9f6125ba5ace7e622314e5f75e0a8c7ce6f70492525378efd5e6c98c583cfc27f80cc9afe8236696abc163dfa8741aff05fe079fe872702dab84c92b2eeeb96326e4ad8591433b9e78af48d63c7bef938f01df89025585271b2a944a0f1d4038c32de9cfc893724e8836b6c004fc2cb327243ce2afbb0fb1fc539899933da8f715a87653e348232ea69ae6f0451c9ad459c01a1c74652f5756a0cdd7e20b3e982a708ddae7398e8badb45c82b6cb83f331a235c73f405e1dd575657c68cb23604869780ee5be858a0a5c7c405b41d8159896178683e3869dbb013e1c01551116b63288594a5c6925c95680b1529c3ea82db1751a113c5bcd9bd9ed3ce0d20edd2a9c4d63ffc46209b8dd2bb7eb4588c6364cbc5f6d23d69c602012cdba8cf172301f04ae9c276ee49eee102371e2f78fe02fe613e996df27358a4844fdf534fb1192fb6cfba91d8142779108043539169df49a69cb33d2945712fcd06421cf3edba0e9d913f7a11b84803e4f2163f0daf0386bee0f8957cdb4176292df51679ce563316a01611c5723d17ac892b3f777877521f2f6dd8790ec4df283bb2f89f89e93c5a896f1fb6e60843c4db48954a262b7d05827c81472739ad2ed4aaeb18fb5a24e12fc2a4fb0a73d85ce930b99ec0b86615348b42ebaa42f96a96d852877224aa944d17c0c3f6ef84037f76cb12ef4d4be22b227d256c2f5e023c027640f298ee1bf46d1738284abee8c822bf6990a238e5fb73a852deee44766495b7a7be7c30c9a7006041cf0112e6514578024e9f6ac26376e9fa1161840663f0079de8d57df4ff0b4ea2e9eec6c4c19b70682a5d981156d4fa0cbe2b0cfb0d9e7f3312810f522d1a1bdc47628760d3c399b20ede30509c6489319a43189ffdeed6ff6794e0388353be68e2f67122d5a05265146432291545cbafe54587e19eb6be0131946ecae1887ccd1504d8a990b5efc5c37c952fe8478ac993b586bee61e718528d9e4c0711a6c62ae62922721a66e9d37d0957cb019d4eae543b2be9e0e17ec9a75e66e7800d8bcb83abfeab0709858b5a7219488b04a1722d9c7f981ad7867dfef47ea2134ff44f0337028994fc20231b0d02edd9290092c2d97e39e62c1a4c91af30febefe6cf867e79bad4f032674650e6dad91a265b0fc0333fc5953361db55aa0afe771e0efc9cf3beae361e5415615f2e4cf04bdfde8b556ff51e9fc00668b9cdeb272296e8fabd45231d9518d64e6c80859a90038c7730ecfcee379316e61f535a592bf89aab6f0c93ec35f3a4a2099a57642e27d736b7c3e595a7c681ddbed8dee0fc15417d1f06a805c20965cd6c1d3129c3d8b67cf9cbced9588435fa9e1b5fdaec025672d86a64d08e9b36987bb5260905196ae08693139a4289dc69fc22b470d229c02d7b2e7da1fe9a4749c10bee1e536751d101dd435d6e9501d21f1d93d5099f6b974bdb9dc43ae6a27563e808321fc1ca43cc0f2917d92ded22bbae75545f873d712f51a0dc83ed3a6955a71af65c8cec0f58a9ccf507d3508fc023f4d589cb7cb4dae62ddbc3eb0f43e2ef5b9bdfbc8ddd00a755deb8c369fda5f4374f2466dffef53721d9593bd456c0efc4ba7e28d21b1fd54b8a9eb18d9b7cf94953cd70a34418a02e017fee73a146324a569b996ecbb5091536a0659d402fe7ed9541f20c1aaaaa8392c86761609f0984c4a4234c3b1a658c5864562f782957ded12ae449477d2865a2a4f4b4f2cefb5b530159ab084606fb1b0e49f885d10ff34614edd0baeb28a76c2a14133874294104c34a654f89e95221697d6c8ce01333f593d9da1f0370fabcd4871dc1c2b4283c49321c1b6d52f83efd96486364a62159258c810a5941de3fbbb390342c3", - "priv": "0c7c3958d1691c75ec7af62d488b1b252067fc298b75656c87608bb94ce9b35b91185c8ce07a307672ab2a4886cea1b04b7ccbe12149a5c887f3598d0307462518683cc8d2aa83a2caf2c886d4145f694226fd1ac6b1ca2b1867074756a6f34876d028dced559b0c0c249383a691ba8bd7f22f2dbce8f3eccb4f6fac690e6c0b84184a0c154110086594226a21258ca3c80d51446212208cc4c26c1834424c2681e1c829832628810086c94481e4442c94b28c8344520ac2911a251214a31110219044b8094344088c904514896544a20199129149c665c4026e11074ac8442ea1060619268944382d183089831670243968e1862121280e5144529000881928101c102ea312529b2692a3a6848b9010c1147044168914c2442014041c016642c409a218089244821b1582a2824d241704ccc02c2120490a840814c70dda168c43262109a13003060ec1882182c84924832459a04cc43291d2868c088864d2c42d1b916c60a00518a76c04023048026e9c8201c41806c2c2454b806d0b37255210600ca62c1c1445d22644c8206819382141b205e4824999088888b84450c40960944492a445dc300a913802232344410628821451112448644831094446d9482c22468140262892206618443208865012135210b841c1184c22196963060540308549168c61b89061462a842891db161221335000b8904b3268d3c8680a0002e4a024a0980d42068e04070e40c6801c05925c2610e4242802b0509cb04861426c9c90708b2010cbc665c0362cd336890ba5291a28310c37428a025194a46cda2489e29051d4306d12190c240111c2006a128389083706148280db406a4ba4819c0684a1c64c5b34884a188201c72d02053284b44de0b84cc9a6455b40466218851b2671a282501ba92d4c8071094724919848024968e2322cd2461250b60ce4365209a505c1a448dc3200da2460e1c680e4400112220911077009b18113b46919b5309a0845e3924508396e02420e8c3846009330e4c22c9a94458404908c821120b93011020050a0500b320118052248460acbb25099360e1b2940c3168d490010c12229408049503665e4846da114460c904180a451a00812c4883099b0308400025c4001591410d42009909670802691c1106988a60d84200e5148894212615190310b41485a822c6046700280245a082018080682942153984c01036edca625242192949225c824618b480201c75114328694826c0a200400334d01a971cb080423a405d0c2851ba21108286448488801c731234668c1102819a8450a4681888840d41869cb3289a3a48d2090690a902822364620316d104385042524a0049281341090b21021314d5440901b077101088d02a02c04040520342e489008a2088153464ee4020113180142042e801229d4247011851160b021a4c45100106d213711e3064153b228c324650a192c98a080e20046e4c4918ca27058c0045a002a53301102030a0b105084b611c1c46dca9645a102842036415a9661a1068adc2608ca2068011202cac23093a02850164e0343714932309a122443204289424dd3926c1087211c409198c4111b13419c4485631410912681591269d49410c9202e10114c43304698024c8406240007440c312854028623089158042203128ca2364c8a360160a4841cc2488392918988250a495213336da3a08061b6500082900a462823981013b521d0a6284c9085a3320a223081018811d314851ca2212333129b942883406209c44cda3488e0102a21813011492cc416901aa805132468c438861cc1600a068923c16d12b505e494210a9324e22028249848cca00121820018931040224849a485620644cb3605db048c4846262212501b944cd3362a54360c812489519040639221c4a48919c864202361139508c1024ccb044e4a040d09a249cc08285220700b404d6400689a003211352448202611952119b84414b41098120609a76804991052904563480a9c0805c8082a9044695bb84d0c394862460493326e109748d9964ddb428d21a111512201d4126ed9980801304c092344c3121023416811b18558b6259cb62862386ecc80802336080b0046d0902c24354ac4887043b8651b042ce13431d8862c1ac28853b64d11352d10b511a4a67124b50c00b984a2348ad2046859c204508800db3666c336710c2571a23031818028720decc23ae277784b3b2cddad9fafac0923be61f70191c71383b2373226a56e02d6743aa82a3bfea22f97d1e46c14d343622869c68fc14244da4d975fe11fca729765c8646efdbc36e9734c216412f2c0a85bfde6de1578363a05ff4450346a4070e2212ef1b1cbfd8c2ded6f209b42ea7d5cc3549e67aaac161e7db8c195a98395126d5b9c41ee210e2fa59c4798da7a09cb3bb2dd12610ef8f767dfd37a76ddc10ce5b273ceee543895efceeb5c37ec391075993ae2a3a842441f2eab5e6115c9bc85c17c00d2dfc2d0cac8d80d38060957e7b7900defcf9961a53ba43022a789d63ee17d63959c76a21a3e78b3ea36d132ca80e90d954200f4251e97403b0605870519277e625be0e9cb26ba809c55fe8bf98d7787f17d174f6861fbc8d38d35c883029e5b8ecd09b92c498a4d6cf215cd800aaabe5284781a9d30b1d6be2c69f7bf86dde4b4e45b5b64d232d4d9f2c5b248c2f2520ba5237a16d2af7289de3380ddf2000e108449f939af41b5a75dff441f7de74a1933e6c1c39020b411b7c53a2c92c3dd6f8c247d255024ce2ea5b2ed720f13c3c0cd9ef80beb3050a130882f2c13419529372173cf52ce7474d2c58f47da133946862417bfc78725bda44bc093b9912335220cdbbdb06815b7e14f74bb5cbe69aee930625092bddbdd56f0d3ed5bf2efe674cded2417b080befbc8b3b9388cdd8df991e3a8cccb453e66c63d72df0577436216879d99bfd86f000eed1c9401aa19f784537a26b351c6c8f4803f9a9478124a6a1b0ab92f4c24332433209f714edfe5c0bbc70b2472b5603d752115b7b994ff4dbb0ecb63c5e4e08df4482dd0256897906989bcb7d7b6f24094d990db6b02b7c72f8b605f38e86f162fadf1037fc3773e1733b667052eb8e37c6b09c9179daecc129ba5d1e1d33df08902f709225be3d692cad384be6101dc3e633cf7f39776a34aba51b92e54e0d9cba52df733758e1410dd0cebc37e89ca43e5e396b522d0e0f464965dd4d65b40777cefdf96011d32b233579f296eff4e8d93ac0caf96f203b4aa8af10ccae7fa6d89e4438fbc500e00bee3a782f027b87efff0cdc2df2fa9bdca98ec99ad94d4a786a8db43e8f333948e3cfb3aa92186e8a0a31e762850836d11327ff7eddcf383e01711ace61a3f1975c701ccbc22dd43c0114e46f998fe6f02a5d7634fd7b8c947770ddd129d309b58300f33cdabd9e2cd9e12d737df54e4a9729c21b9bd8b2e2261fb900a0cf939c610601c944626e616fa41a861f22e1497023310637736dcc32942f6faf2948bcf987d47e50f906cd9655f2872197d6f8aff595173e2a4bbdb6cbbb14475d02620fa7d210a7902d07d60a482111836c5493a693a884a52e18bc56388a9ba0d0c5cdf5f1b31095f7d8f713236d541d1dfb9c6f25a501af55e8740668f07dba330ab19ca5babe92bf504fc63450c472652c1206c23bf20636a7ca6f1654d4ed2fb32814f99945319dd73d0b0b74f073b5d45f2a05d60e837a76a75858d8c78cf9a0c2b1f2f9c8fd6ff69cae793b342032ccc03c383ea11c8b6e78b527a4b70b11cd5ebe0772d6e95cd0d78309abf4fb2afd6e551f1500a444124baf98702f286733872c734e8cf4a8b98d7961eb2c68a44471e59a6262d28bc6326fec59e376106f2bcde9fa09ca95ec4b900b91fb7b6687c71116f66c12f068a96f8aa46f07a36c5a08c301098dcf0920eecb34a0b578ff3f4528ee681150ad667ce66a66cd023a88fe86a26ae7766bf6aa670d39f51873a0cdfcb5b181c4e9c3f456042a8d6ff28154bfc49833a52b8aa445400bda1767be2fb332d9f9fb8c5a7cf65d401ed542d46847deeae0a1d790f04f1011b711be770fec5e8109a3f90c36d28d2dde54ed47ffcd247b40a0da79164e966251b071320321f12e36718f78df622943cdd35bb9a2a78fcdd2286a4171c0d52859807ffabf9c8167fc1063133907739375a3f083a6944501c07d8bb777d5c1b9f413ee3431963542fdee7a8dc58351b5e8360cc4d6f4eb0b521755aabdc2696cb09fbb71573cfe0e933aa873473303013d38339067ae35b88a48820b8eb4954e8e13f59e1bd102d896ffbb937fe12fba2aed99251cc8187df954c7bcbfdc905e707253c0a62c04e049a898cabc6a1a3e030fa9d668b3a342d9995008610df8259e52d7d0e728cbd8de280e6945323e133d7f4fa67f81edf98b8891340d93edd10151a26452fe6b3c283027fd8fb2c925b04e64fd083ea0ea46d84e9bb21dbf392c36f2bdc5c8a4fd6bd5041ac24b4eab65255564898b99c774aea9c369ab4d31858f48e671cca730d91313d1523cfad69f29b4f297b8f0e148935bc1d79aa0bec6c00034394e78949edb0f2e5d00a7e44284ffcbea441f3da79275c04bf0714d2c4d84b92236ffca946837b69e6ece1b79ff7714d5bb032d045fd81400f9b776a2fa7ed48508ba6c2552e076d3cac1b8239f54020aeaba2e3caa2c2df6fae061e75576a8d6d763027fd0ac32d17b9cf5cd378d1bfdd56ce2fd9bdd349a016aa0b4695ad1c226e25360831c0e74bfa0aad7d45dadd486bc0ee8b65ff7245d70853b98ad855982d2b2d75d2cdebbbf000b182d24197dc167afc88f6f5af30b74714f252af84337507da403225a09b8704c080a576e7319f71c734fe74e27ae306d7e2cfc3b6d94c7c0494ea35e26ffae6c834000e4ca8437064633b363d0d7ae9ec66112784fb3dc94b88d644930d6bbf2acec639351e6978956d475c7bad9de5e530b8c7222eadc488b501d1b0aa548942ab37b4b04184d2d94c3916442ff9a1828515d7410246d0555f2a4fb580f86738efff43fb1804b3665469b35145984dc79925c5004579e9015f06425d44ba3b6350a5c8ca74499ea13ea618c0bf3fd74010088fcf3a3c16a1568045c0d0de89afd17f689917791557376c280edd60997e03c118ebfb628afa0469fc5ea2f675f8726b6dfb15e6aaa46300b6868d9bc8d8479780c688fa2b89db383ad15eb0c68d295451144a6ceec635db6614deeae6e52c9c7a9868fba6636e834f1ff223b8c6834f97bf54d4ef173f5b082200a917938f124f107807e40a0e280d0e13b5a473c7d03453eccafc15a89c67fec69a2a84835d72c5ee83da3fa97529a63ba86efdb97cecdad2ace6488329b72a96ba26341201329e7d7781a5b696966f01505885d5c521af830740aa37ef658af6d5b7fb7d1859cd13ecfc9bbf7e454917fa1c460478646d622e2b9d8258112509c944dac0697ecdd90b04641e341da9b1e45518a7fe62477ae41106bcdefdb62d162150ee3b02948959d28fc8b4fb92bcdf2a5abd3089de3c7efa70fd07f0be86099f636d725d946b061431b93e3245ef64ea04de651cb3bd13ae6d1b0aa36f75b81cff1f3c4d80e3834401b867f052733be507cb92c379d98a6f5c7fb255f7903d1e855ab2126022076052111d6b885549f7dc4c4bbf9e8834922b2c54baa3be22e8c288772ed36cee8ca9fb715bdf2c97a4bebd6f4f3b087498f97f0f65914770a3f6bd9af1273abd70e1c24bf46b3e7cb4a79549ae5c2cc4ba0bf3f58314484fa73df2258ab0063b7526c4586c2d2b11545c8dfc3766f47745b0508a423eb15637c71dcfbd3ef5a8d2b27e3ecaee6b1330053ad24ff513aada5bdd1fce2e8906f5869a24f357ea9e2968cb9c123dc9e6b85a56c8576967c64b045084aa9ac8afba8e261f29497fed4eca9843ea003e8eb4fe2e37b036740ed86f30fce733aeb771f8addb2b906ea109d0f857b6b802870663991339a56f708070be697c0dd26d4e8f47b780d3def1f51dc2a377f1ac5dc57ac17b4c845cdc2e1d693e0cdc05a741436d8389a0c8dd8c840fb1806a647ef84cc63847d455da1897dbd2fbc02e995502d4ffa164baa406aa3be79be7ed3a9f0b5e36220525af60d60fcfffe7eb671d9dec23e02e8d527fe0c961ab58038c301a6217b5314d38cc2888de4998c5698c8e521949396f61c1a78ae74862d815beddc9d6212fbab311167263c24ed3184e02d44e22320808ce9c642f0713eaaf0806fd25017e42ad63d62f01726fefd61f52c049f70d3d846a4bcbc32b8428f905102adb0d8b7c3c9deb903b6d48e10dac9b4df4ca5cc1d6b73b93de12658f598f3f964de27de616c9e3f8153d2d11e2581a2e8cb145342eb47084aeddfec7b360c14b2f443a8ff7eb69cfbe7b5567b61302d3ba2daef328614053006989c1cf6b46f9fae9edd8a459e46f88a8e857810d1f0809269d40d3bdf7cdc77173dfba70844f793fcfb399ead267dd38b01bcc6dff0bbca1261e24d7233ff505653b876886c03ce4698802dbed18a2ac7e1d90a6048f4edd8e8a626d08248ef679d78f8d3bfef3d862925668c56cb182b1685be379c06f13056d785678e3607982d4b5fb0e93afada0ad326763407afe0eccc16c5c565456ee2c1d9383b64d941acb59a5259339d7b2b7b5ac059a48afd02d2d06eeddb6320a2e32e08a20d8c20bab0f8a9d8da6ca6a1b72854a4c286a0c53c2f2b2612076697d3ebec1283c62a11d58deaac60dbd6090854546f73c19d50948aedf670e2da7462e6e1407f972d4751447321bacf13f8d901bfddff1182e3f19b2685e4abb2e4276cc31f6aa71df39f1137610bda2dc43c92ae773cb6090b33301862875e448ae4f58d401cc6660bd28b284ae7f29573ca647" - }, - { - "seed": "1847fbbf868ce536b0bdca3c25336b6ea2eed56a78ea125e3ce2126d68d38aee", - "pub": "49d5826012d41e19ad641b5e27d6db70e23c83205c5695157656164cf26e1bc1abcc9e6ff0ad68cfd2ab81d98013bba899149cbc0b9e173e53484433e7fec87ee884766c758bb57e605e787773fbd73cf1023908108b587b0ad5b6353dd72fbecb6d5c798472196d4c357b831482ea9f1e198916eb2e116ab61265902a85cffcf445ff6acff596623bbdaba33cdb223923c098f1596c7af2d667772cd479de3fc05311f763150d6c8e90a5ee92fac32ad53ecde49d2ccd5ea3267ed3dccfc73ae5eb87e07c252ad2d59a4a40b36df73f8a703769d18546fe83c23c748839ab82f75bdfefa58461e8f14c87207fc6a646702fc224ea516601b7e2f795261d73717986229d02dd48d992e4bead1576da5c3fac3e2cb6894f06d39fee917fa6c3cceb91b5f70c5700606226b69333d5819b24f003f397b5a712553070b0812970d0d839a530ca8e2d061d0e94f3c83f123a91f7a671eae15710ca9bf369facd7e7e0c2479d57f57f4a2f22ae6713171ddf1431a2efeac6d98a23cf5a96f389bec4a509d59c7f66ae7f9118d63c1486f45ea29b303ab3a2c1d4f32f0639df0fffc38c181c3f8bdc29989cba9c55748ce464fa49bdb6ef51f2aeab88c75f8500b4fa7f32297468a27d5cd0e840e71905650451bff23f005afa1a3a5694f33c6845fec1beeb3ebfdd982c2728e9453f8f78abdea7ab22f861980f20136b64938f0980fe6a8bb45a025f393228800dadf189e11a71f37e820eefa1c815f4fd15f02fea908f72126fa79e85624d7f2f1c1608237292191a256ab7e4070f95d6fd70a8befa1af5613150c4cf8ad411eb9ade6fc21a3cd9410833ecaabc02c2df707a81fcc36fb9422611264642a8a64f479128e2320866a658937d20b4fc9d129981141d61993a68df6acedf3d4eb8907948474d97c91998ac7038af8acb5588b626a2f0b8efca79b4b83265dd8b36e7f17c5ab44ab8e5b626afdd5374d923eb69b1f033008f51af9e36dc13bda2837b59fdab6b16aec508bc568e826adf3e6ad2d1e092a13aee041d4b691c6807997bbb36b779caa4c969ed7ce6b85befa537b184893b94e002e2c23e9698a2b5a1eb520498ff6e1e1456a67f108abd2819315acd7ff60c430a97d9183186222f1912974873d758a89b2626af6f3205cf524d16086ec409540d3b725e62210eff044ee8ef8b5963042c86a7100e9ea89180f322f59552c106ebd9433500bd1da4874c9963366ea0ab88f6a7a5271e688dc11ea9a14a44883c26432abd88677c0091b7472fed367659c41979b8a23488eeeb77c763a60dd83894a86383f5dd034da16ef38e0923f40f38c5441a91f0d81f65d55f0cdc4af4b0d6156da55dfc1799296cfe03790dedf04b4eacc417ed8de0bd641fe255fdf36c50311cd905523fcc06a1fa33e77d620a46209c32230135e7121d45fc7dbe1a8b72c61fbad8c4c1aeecdc53791e61c01bd1f89c34891d53665bf966061f824607bc77494e57fc1f352ce308de0396da614176d6abf50f02d8703139409c5d7f6e4d9cc612a27cc222cb47db08432500230e90a47e04fa3f7fbda89c16982df8528cb837b4d55c7014d6b07eb375050ace7562e32371864fe37badb198f8063a5978c749e03600d6e6f40620896b2daad6ccf689df313801d13c8f851ab084c2e4c895087e11f8825e416a1b7107fa56b5a72b6b580e16e0fe534c231d9d1695e08dabe7ae9347612da46d186b407652ef170197f09a859afd7b6a5c1bdbebfa146559fae94f57a852b0df1759b2b542280fcd5c1e2c4144b45e539624e1a551bee0c622a9cd5e81127b4e345002f7e553e51558f699a94e2ac410bfffb11073037d8a00d2c0fcc36daa1c813a971a2e731dfac2678b5ed08c3056409799f1e13e06e21027d1127804d290bfd4351ac55c9ed74245711c04e5c3a8e12d3b71966b502a49669de0de72213ecc0c4d4874b79097b1481e9a727fd57d891be5fe146d9e4c4a422a881d9b6aa241c06290d9ced7d240e275423c06f6c5fa587b343b1de49fff7db5180e3ba41ba544d316c316524b70c92ff745a44c3d382166c11d16798d2ccb0e09102b506d773a2a27e9a3985a598e3b86126d0f6e21ae50b239f332cb65caf58c0f33ee07ed47c9480702954e295a0e0c634cc3c49ea61392563355135bf1badf7b540b56e4832fe17b59ff24a27380ba7a213d1566f2664b274caac4080cee41f59e7e1108d66cc1e6fe19c33b35a3ea77712d3900d3b2c08dd9b460f48f565b767219039422948f488687d18d1df6c56db1d649412812e3337a53be7d74f25b081c09b7cca2a705363b9cb50be626edf8178c62e25b8ec684981937c2d46f893e32c2668895c29bb4b9a2d1d294bf8584c8d3d8dbcc0ea4f286a25b7625882a0fe2bf39b6853275b0c87c37eff55ed763770640b79c4ea80d66d35ed0fe31dc2864c53bc970b82fea147fbb84f623d7233406bc2c18b672cf906b54c45da7d6f803042f9696b3cc40687b8cfe1f49541f1282008698ed308648da4ae51420941edbd2d72953ef7a33d81b1d973c37e691149a0b8ffd83eb6421a65074b5053cce43363843760f9fa79bdc2e1afa507201cf5433011633c266a268a200f721f10c11180152755b97f99a7108deb8543439f747d51e4bfbbbbfa8479b60784fc97d954250b44fa8b9ad6879f79588613e35ab65b7e7588d1bd414059ed53cedc5cd60f6316f9268fc4a04c8db0a341566c5de75de8c7a2ae75d4f212900463626bd34d89c4a4af90efcc46694b9b5bdf86b5ba86743173872d2ecd2f2b6f123ef737ed5e3d337b8c937daad00d4b036149feb0a06f33152646b54cb2bc7af7a75fb3aa7c839227696afa81f98670bbc37d7a1da99c6e4a93d3399a222c365ae9339ca708ce28c2c4115d89245ea0dedf07c93bb6808e1d9ba99685e709b9e50b513e55843c6055ce7be089182214d67a3a3765382aa4d2940b88b1529b419b4ed734eb0895c7e258af402870366c0c96eea543b1d4c91d7730dd593cefadbeb89a0e490d4f5dcf7013fca98964b9ba99e9748ec5a9fcfd8afa39d39daa71f94d51d961042545647281e2003f7cdb3bbb9dca41f0e509a20d334d695ee70745f4a8f7c1e34251a4cb701c29a19bf5cb2e685db2903bd25ace697c84b7fa12e75b7f3540a1387930610d18d8b5703f85ff121be1e2e1f891ba678e2cfb8f8069499583dae19f027240437820ec237144a870a36ab883117a5c638c3eb05c7ecdbea3fa631cd215c71fe55a555c2ef32f6bc1e5b43102ae418454c624f44023ffcb161b09f914600eaeb2c172b7e5d614a33d080646d8791c56421ae865fe87d44d696292778cb84b4dab4daec129e64c747904ffe8178cf4417940b30d89ee12aac595b1178f23e636db30d9177891b34d95bb1c6d53a60f89dc5bdc71a63af690b92812859d6987fea6bc046f088edaa8c8bd3ebbfa1deea3d3eaf2f482c1c7d955fbd93de9f4f08d6f8e43c9e711b2d70654b9133d41cbb08040f33e4a8ad460be347b9beb5a37b7922491cc7138a4db8eda410e08abc7698f0c4ee65f267bdbc66b4cfd86f500a0b974b03da885a77159291ca2b18ae57221df51ecde3a6bbb886f691b83f970dd173b302bc4f3f18af721d6cdc1658bf05e", - "priv": "49d5826012d41e19ad641b5e27d6db70e23c83205c5695157656164cf26e1bc1ccaed6140de0219288257f66653055a8d61d1c477f7231d5db0b6e335d4b29d9f971a3287e59a065674c20d00f1d6c14d683ab3afe97ab644509871e773ef29618132985c70d2ca66e3fe4a010b346e766a8d1ad842d7d56f08ff9313a8b9d5d1823911c396503382d04c64d61384500827159984910b1041a844890284043a80550442d04a54c0395858200444a16441937409c848cd8c849498821d1349091b841184162c046054b98690990900cc550dbc84d6242825930720a1630941870d9266e60480a603410e1085180a05060468ad0c44ce204300bb88822229120a0612414208a28520913460b2606e4466850c08101082948340a0a209019c028593228a1006ae3228a4ca020a044611b47841bb168001232cc34921017705c90851bb705d9962518392109b4680c01458ba6001b49280aa585024250c1102e1a288d21244224380ae40431c39021c836900a480a0a88301ab54990844dc1242ac948229b164562b08594a22990920c1a138cc1160cc4b200e0a4719a006889348cc2342a03826cc2046e0a236020232598429288800c50383019c00d0c31710b040dc9a2411a454422c37080b2514296110c42881b0665a106651417409318000b0342492845910211d882844b4889d8468064404d4b202ce32231481242d4040ccb166819a10021356001994922834010107212902ca4122d1b06705410062008454c104419330d14027010392c1b1584db12899c8291dcc4105a1864182300cc0284c438440ca42d51022d4c860551924d12846d98282c4a320d09c80dd494090023815918059228454844092121720408706228296126214b20200a40406346904c326a181142c34644103852409810c912041207301b91090c16228a3681da203153908c03122a5280449a40304ac211419864e1c871d14292040261c1060884341009180411270c8c46069038910043861cc484134680881860a1a21004a54023016a44c6719a4686a2b888a228601b3604c00000c3464861b451c3044e89b28c2114004a867183028e942824231720428289630892e02451e2a691a2a229a4825109046cc2266ca4306a92100504324861088c100505a4a24d8a366408c5409214654a2464d01860114245cc888c1b058a209500093912e406711b422d219309cb0661e034424410125216421bc81050c005a0a0319c340c123100d90420c816124bb6280c262914a970ca2664c8884104029110072821448a9494412348441094800c142a12202a188661ca0882ca182149000494940c484866c0280a21b2090bb54510028c23b18c12254990220088982d5842900b400100388918b9694c346113a5684c064ec0c40d9a4212cc90301984684930642111001bc241e3806144b628183500584642d824821c294a11926824316e22397151800849b291899809da2801c3928549302a0c1560042006e1448214a9855c086e91083282b62963908989466a1a3225d9044654404691166e1a114183c28518888424c780a4288ac82426a3b82dd3103109014a22382424c240083984d92231e448499236840839100b4488a2a289021191992820e3b22ccc06062209041a030d9030088b146e09424edc820d4848869cc411640220a1446442b6256492240c11020c9089e484519a928114995101c66893168e1bb704a18489894808d4446249c22c08c70c01446a99c051c8b02910110c41202952a005a344841cc12424000964862923827018c169a4084a13a90cdb222d4c401208002003b94d0b866841026118140e82a849098985080506a12484da144ca38690c8400980886c50424a13186a103381c3b0800023481496451c001189120489242911b4401c9300c4b240c8884518c00088068a0c081123844044966400b808d046859c302521270813c129d242295b486963282209368a82b84041120ec80686520481d948010c406003448861462694c4700ca824a2424454282a23054eda0611d3345259b43194c421e3466920176201332601b70d8346625c92245002890c45888b020d4c182e04018c59186694482983862c54c2441a1188a2a685a1c4292094809b986002453100357088344a11b40463340cd4808c10074144384ce4002d0c262adc384552102ca2a44c1221461870a85b7e54372e1d3a3607e90bc333945811074fae7a807cc61227fb7d8dddc8c2193081985441e1def0a866f9e297a06acf9230b8d4665617f3302d75fa8335f6fd1678fa35d3d3a7959619224a0beaf11aad15cd955381ff4b28f8cfae12d208d692fa202e6e30ec1f034351dccd37cbaeee9b8a7aae0c32f08c69e87947dabce87323a7e20e90c803837b1f11a99c7552fbff7224b863321342ea09451208833db34cff69502a26d9d0a7946dc3612d94677a14ec8f18f0068156c9c8069c2ec90f4ea6b4eb8b7e64d16c830c507f0591419a0266326cc452bb170e21a4ebc986f1237e3d56ce6d1c51768766ec7fcdc6bfbff7edac94823a10280ea700823e24d7c47babdc351e21766d35c98aacf7d502646cc52c8b4eb25ac323c0906040ef47493e2946a813a923f3568d8cc144a1660b68fd315d309a2bed3af9d9bac12e58f87c7c9cafbfea2e9fd945aa40814a46a2f7bcea0d46d2393e1d3eef0a17348b2716c31b9e191b59365512fbc61d8fc61ee9b380b212452492d4923c2311ac30622a70df638ea6388f5bbb86949586243450cb11a2ada18766965f009ef148872d30324c403d3d79d7566d8e224e47e5b4efca891526be1671b08dfead0974f06de80a311941501c40ccd9d4d4b89c79a7dfb023ca9a7a9fdea3d02a097362fd50451decdcbd259a80dd08951475ec2a8c1200de0471dbec4a2776fc28261bb702189db7574fd92e80066b85220d52d5fea77e4951c7ff19037079c48f315381bb885cf7531b08cfd622756b5f92f098b976aec9be4a4d6141552d69eb01c221875782688efabb3e402c07cd2089c00beb74e67c92271fc5d812c78e0e5906aaf040e61309fdc9a20abdb464e2de78fe01ec7773c6e7b548960bcd1ed08a1768208131a45c342ecb84af64d24a6f43961608df9f58c315a253dc02684671eb074120b74f589716787673be401b25c17ce67eec866b47f48190c12978a776ad0a987d9e4bdac0a34d8cb29d2bbca19a6d0f24edd0d94a5ffd257a18a697e8a8c7cfa25cac6bc5842fb76165fb4b7c2de7bf66b47f05611004957a447cf616a82837b1617065f36582d4f8c6620d97a4263376e391f44de5dc61f33f23c32685e81343f936582e1dcb00a6358d8cbb5fed5a6654fde8d9b6e5baabcbeaa7b50588841af98ea9cd9aca3649f1512bfad4c20b5984f52fcd7aa3d77c73a6378eb5e9e1396276716e53e3a85f13c6a3543704b1afbf27fcc8884f3c4840f7baca77cf33c72878378489df9d695a0e33e7fc8002cd02e9ba4fd7d4b4e1c3aa8667370650e7d3d21e20df9926463269f7ea232b8568d50df45d99e53fa542742b72f49c0cfb8b52fb0fac1a2e0e8b2a1ed1af3a53ac0124aab754dab77523f29e00965b85078444791dadc0f071b002e8c149d5963fa2b71f4a560c533c57ba7802daecee31068c95bd49ff2a236b66e814d6489731caf8aca3d91f57b60ac06e282e6be0abbc635676a8b138c7cd8d14eec0863a3f903f3b035024f9f633fa5dc64f9ffccc7454490143eb15a2bc999e0f33bb4ef20db81bc4f6bd9d4bb1616886c6a5886c40b5d36befbb69e7ffabae6018cdf3cebe83639a3e593d5aa1d493870335b68e62745401fdd07c8febcb80e4e36110ec02ec3f872ce681e8d217c8ce3f81cc8fcb3d1e08c317c353c86a2d799f4013821c32a6d1ee6bd3acd58f887afdae4c32dc01c96123688a5278e275d0198ae43c9816d68b29a328091c203760e485e5303f5e52a24c1a2058682a046b785ad6ed60390e80c8de8f5f452856bef71b272fe0aa24f1c5e8da32fdec09e5df009d667c9eb7f1907bbec78f1c934408736082d3203d9d66653f4b174cb5b8878e50e23a9e09b52531f03c8a93b5f29cb9eaed48bd19474299cf05ddfa7a3c5c3573ee29155d9ee706dfbbf6b3442d6933b6d632b1055ea351822ce08f8d01dad51aec5c98cf047e18938465ddbf3abead7350f10b3d607b40d433cb71211cbd5bca8b4a7b93376e89a2990dacef3db2089acc86ed1c889db5e8f62edac2592466e787f623dd0e8870317a9625a9c30b093adbebff97b118f3873d560b40419a2d5310ed5901b8e91b4d06e242a27da74c8912efe398f41b399f19d4a26220fedf542d5d919c22a1678811ea9ec1e6b754db5985fa50f373aff55307ff16dd039985b13bb93f330cdc883f41a384f4344aaee85b3beca2d0dd2a236264a12221735cb8abd914fe41c1f0eba7a822b5054933182a1fa3b8dc4e069ce214447839934b8fae87f2dcf85ed5533f75c54c47ab77e93470567fa4553ba1d55d8d06aaaa6682de5ed68e2537238825458d92ad0a90fc289e809de0ecc37a0358ef452fa8afebcf5eebf4c70236ec57ccc7787652a20debc38be9f34ac54be0738f9614e64a631dcb143b8049c101d1abeb327cd687d230ea5f9cf3fb601339dff79585189dd2aabce780fa6eff36e3ed0a49514ffb7d7aff52b9b4000bb555002573e3039882b87502a9d3dd8ee36213c07578371fb8abc3c37743ebdc97466cd345abad1a88aa02ef4219ff4816ed5382c03b551689a3d9704a05c9eda73fba75ede37302bf4855609215a035c65f2752fd74687089be9817ee58ba107a1111dfe8be66d749558093c2d95938427d4e64fd26285608c047f4aeac9cb79a91b7bf2e1ada230756f95686aafd0b29acaf9f4c17d13c7656a5b9e67c73f6ea2dab220d32ee42430eba77779e3044c6a76353aaa94721d5d0f32fe7cd2d4ce2511ddc258f678bd5c7499bfcec60f04a12ecfe2f8af240efcea9d0f9a9ecdcefd97607804fa7e586b3523e9fcb104b98c6bf74cc3acacd968120a9102b079c338d778b2f19b6ad82239a472011fb8041b3c734414679403e6fa7da3890bab54b4d257a0b8f880ed30f32cfd9b7c81ce5cb009aed52f4b564be73a471998ba5732f6d29fad7af0d066a4ef2a993485027cc2e41eb7229fb5ea9058d154adff79705d070034aea98fc19900320e0020cac4a6db1c681fcf190aa49b6ba3d8c7f86d4c5573cac926dd48a56295434d1b90296be44cc7bcfb3fac8455ea487e74b0c8b32e85078a90edba424809365c7c291e3fee828eda7b1dcf3bc6e91c720645846b0333b37fdf0ecb28ff4f7107be1e69493a53e7ad0a93d8d978032adf4de5a45839a1f6926824594f9b5a77b83cb5f0bb7a13cdcc7064f630a2ed67038d553aa03e6cff7183494a7f5e1eeddfee7b9a850459649f1a8857928f13e117687c3e46c4012d029b31b7377c0f490b441d3ebf5c2a304c8aaa1e07f12d0b42bf2f216fdc6a6dac95fab1f601e8bace2bfbfd56e01c43fa475a603eeea2713c05904a836e6fbf2ecef22e526fb32bdfcf3268cc2adf6888682bdbe13081cc0d32f6803c917028afb60720a9192d207f1dc9622feb10c9aefbfa6ff3ee26a8d6fc63a4fd81956eebcb05c1c87b90e5e4fcce2ac7c1ad896aa11089141531f2e102cd6d2e707c031307031c4aec707b575149596b67ab866765f13ea7c034410edabb2929e351fa540e3fa9498c5a75e604d7dbd867688327fe6f7712406e9e604504e07d05816f95962883890a023d512f5d6043202e0c99bc1a419f99725dbe7d462585af15edfbc2e5ce6413a9e70f239828e7256638571bb5ebedf643acae8c522695f795bd52ddb2085241de56d5f2c8fc4872d58445e8af237bc17502979248ceb4e401f7a5f46c5fc5d5d34b33750afdd875c8d2df3663cfa9831d3d29346b1efe5a3ffe4dc5303d3b22ce0ca58f7dca138f8e981369fd4ed234fb1eb6da9a0a55f9bf5004cddea1a8e13eac57025d7ca2abefb56e356529ebd4b4d649a5165897b62cd0ae21b5a8a70faf6a5e737845d4037701d2b539eed43123e7b27c362d6b1e8bd817f20585ddfbc0c9010e446c8e62e3e6eea388fcf2fb4f92f8d7cb2fb405cb91a38e6a7a683fd7dd42d43143d5bbbaae2ed098bc4f576f2fb6df8a0645e176651141fac8afeef5e10c6cf28ced9e840f9ee0c1d44865c7cf65ddf7bef8c180c8ae326ccdb5314bedd091765906b529d24c00219bafe531086731d2d9171229d4a57c50483580b4934f511d1c83094d5373a97d455ae5a64d465ca6bea9dbfd442f2359e4af66aa36706ed25befe573ba893b4547859554b972535f6af1b2d4fccb4f99a7914d097f830fe53c8448810679ce7d403e95d0e436837120336110240b7171962284af8b8fa579571c4bbf60b1f6d081f00cc234df09b2e096ad57d1074cf57a4e14fb9fb5be9c31cfd8fc4a1623cb8b9093d6949fbda1809d69fb16029a7c2c612752e105814ae6178898c32dfde101fa64c1e3f95e6bf3ebc06130bc635a44c38cabf291b0ad5f48f318ca482b15cc5c44ca96f8902bb28c2362c47f9ece53e0bfb210fc4e47c0d09babf916cfd09acf47010aa77526b22338977a3d061bc0318afdbd3a56897abe8bf22eb005219c09f055b0380718786ebe0ab9fe55b6883cd4d9d9dc76f28a0e4a5b38e9201df9c50fa9a4406525ecf3aa876ba0ca75238b327bb5a0948beea0bf27fa0878725671e786175872751fb27abc85cecc7e307f4211bfa58023b172c7634a8a079a95440cd5a74be176355cf9feda79ef702a601f8e45d6831b16ca7b29a676f59c70fc20fdc16cf22c614a038f99f6e594047c8217ea501f4c90132" - }, - { - "seed": "cd86148f85451ced94f62fda9b7765d2f624b55f25f042af02d4d132c9c6ba69", - "pub": "fa0863ac874ddb903e97b70d9ddadab5f53be7e9cf8180f800fccecb487492ca4361fc68f737d09977a8a9e259b5f03fb9461be2b1aa041c838ea2fb69163d946de5b3d2313c3454107aa466dc994c6de900eb338b77babba34f2cd8321c1c0bd9d4ea793de62fd273cc36021f48b74f2598f212c2d3e09d20fdf8a5f84c8d81d981271602cb3087d7911d9bdca93f18970d70bbbee30a86cd997d5bdef9d4dc84ba7b55eab1d2f96675bf895db0ada3381438477a2edd71f1c67aa68a6eef8199783511f0b6a032b8216a9492cd5b48f1d0ccee84666926cb48e93c6301a040f797af01d7a8651e33a17a4663a3e9c9feef8bb24d053744dd44c49db30217e7a70cb7da2668c3b4f280c50a44e4f8718f23cabefbb85a077877249e00c32a45c155acc5fc7a726baf7d5f9d10b701523721a632b658d48852f96201aa04cf0715c59408efec948622b46ad2418ce5212f162a2a6d4ffe526287ebd07728f61c60f6dddf56b559902e04e821e73685145172baaf47a1b40c235a5234973d1ec062ea2efd70f3a9ac2874dcb933b607df93f003875a2bdfeaef166ae8bcc0460f36aa7fc3d43b61a9de3c64fe2628a86b51db90aec46f6c12f9f8012dad16718d6197f80e4639509c859e55d3ec0ecedadc3749d76f6df9403108d863c9890f9fb680d75c11eecdce4af042a4ff04d0440cd219e9cf18f6c089437c8297fc8eb29191dc62d66cf0a5d6fd58bcbb017cca90da24eae2a9a194a5421c251c1dc379d898132943e452f21e2a9aac7e5931458b68cc8772b5cd2365c922bdda1e376ef052c22c824b62e7e803be5868f01a6110a50263c3b2e8b8b7e989681f66f1692d913d4ac7a755d7a4fcadd06b3045a72ebb2d8782a264fb2009c30be565c584091826973e254bfd725d2e0da1fbfd45993c028667a4004458bd59b34f5c68e19ebc924440c0e5ec3e9b0e3addd92eabe41aee10b143b3ba12e6e3fb9ccfdecd835818d7f4021149ac2530409eec8ba4ca3959e258f8c6436036e0f0a78de47526b8bb4c74eb25cafb663170dda3a345f451ab65be2372ffd805f3a7d3d8aebff973de599f500a70b2928a834fcc817538ffbb9fa60de5cedf1fc984d581fe21978d667eda4558e33ad59ecc8ca016b80356fc071a9644eb050dca2daafce632902e85526b7c6383db92640f9bc6c715046fca09bb480f8d7b1fe730d6df3ba12aa0a466006244191cb42ec7cc9f87ed343554978187e58060ddbdac380a5b1e4eff6848c6a87dfe34a686b7fc609edd4e8bcdf4dcbf5b51082d2e39a995feafa5ef07594e50bc076d5c5045da9f9c2bec95f216eea895bcfc34c7fee3ba39057ee16995844b5020a5947a710f761c6ed7247e98f2df6d02c27f5e72f3799e74573440f7ec7d0d484e7b08eb5c368ded299007798642f2bb6b513cb80d357fa041cf99bd966e70dbff12a4a9b3ee9497ead5f613735ad8058181cacde722b71e09b20abc8d3c42e8a01b39c855220a6afca377c777a44126f6e1c06d0bf8ebc325a3cb267aa3794bec4993721bd802954c9e6d959f78d0c9a01704f287104712a2e43544a280541035bdc2f3ae21b222628629c25f543b658a07b823473108f79a999157288122ee34019c2e2562e730d7388541db3760273832b99d6a8a444fa0625b09ec11eafbbf49ae87db2131f7cab972f2471eaeee10a9a755ae70f32eb3eb81ddbeba0f627b6e6b3e24b5965e0c9c67331e175ad9a57a2df8d7809a0b6785f53861d4f8f9c4166e68ae47163b47f70f011579565f272d866a9263fed7970ae0a4108bd0fcadc6e38d074dc1bb9cc52f1500cdcea7187fc670dca9601adf2ffc424a5843a816904463751654aa2410fc53bc310c1f1b7375403d6dc01132cf24a92962ddbe24c3a1a88662cedc1854482c61505a5a5e5a6d9c626974f0d8a76024d9b81df4dad14d894069a04590c60aad496fd562c41a8392efd9f07f71fd71b4815fa75814c1db3b70de5e7ff07060a358106040814426d5be4bfd68d8878885d0beb11a2e32afcdb3492ff2eacdcab52c1346ea97d41772e9816043ed0c5a5f4873e83dc379ecc20015112be020c5e2ff693c2614afcd5736f9607c50ff47c152493ff1530763011a80760ad872986938f37d93b4f904490b7c44b7e37e1105315a1180c96255c2d0f28abed61f81669abb010b0f3f6f14b2b9079d3123c5ebf5a8ae0567d23584e9975fc91cfd5007fef0b6e53ac665c7a39a6d49bf6125d6fec2168736d53ab5acfa1ba9f48f4e10e2a822af6a48d1162bb9d58d291bc112739ab562ac5d8145fbf769490adb9b281f3ee7919a191e18ca5bf94e60131d02dbf687a96c1a86fd6866bae5f52c6f1f5c20e23a26944ad146c46dceea0ad6d61839a544d1c8c8486225460b464c64016293473cd3a6ccf6a6ca8dc2cd05857d993e925118f43a41d8a1d1b63cfcfc7a4cc5b9b96ef4bbd1a7442115ca7c0596bed13a7a8af2fc0deb516edfa66739e03e26d78a9b93338640fe49b4918b8ccde17636e11b24bee7e1fce81a09b281bf01bf099c0690c1f24dd9249bb6547959e9b7810f490e75a84b71657f291ce018ed46eb5af23af4bc53d8fcf71ccd192b757f4bbbbc4f25359934582778a4136d6d919aedec86b9a39e117063d7d2e346020957b7d0b06868bbddc455eedcb82109937d2e3acf6755506028efdc86f104f8dd05dc5bed8e9a3d58aa0bd55bd5e54e579d1f7d4dc65374761b478ca5fee49078abb9114f9a251d46bc6fd0bd4763cdf843becbd432a672ee8382a55b5287cbe18f10ad37e3f78744fe9e754c39901bcef5204063db00d66b27e941afd78866fb67dd029458686bb1257c2ce7a5cee9056aac4d57c666a9e98528611eee60bd5951a5c182aa3eba011a7f20fd88a979fe07414aa4933604844e3b7bd275e82fa0c30e072d7aaef9fdea7eb4504175abf5edd12c44ae3ed777f6e8c1c29c1c16b813eb4b08d1275e59ee2315912e1cb42b013b4748d08841f0671412bfcab5f2610d567621b47d3098e1f82e5f68675d4747ae4f711c1d8fa4742ec9eff63356a4a629cce8cbebe56432410a15f83845eb5a21ac61a4fa75293acb564c2913f0740e23dce1888a0f4be2e8de5f81ebead52c666a97ce0150c5a9b7be15cfe2e126e0c4c7f3a40d69d80592fb12cc13cf1b6f28444701c93a9f813f81d817d77d91b307db1cbc6571e08fa8b4083f2d721220cf10e018d1d99ff635c9a84a27508a4e13b5dbb6cdbb7ec5304bde631665c0a3b74996b8f2c6c48fad6448a4f6add1a9df0b064d61c35ecc26efbdc0eeb84f0967f96dcda0b49e8fd6c77570c2a383e7df90a39d2ec3405fb50dcd08936acf8001d24913c74a49468b2a449c06c8f28b784fa080038945514967915eee2b544ebc687fe152c2abf0a7f2a3cc787ebecfd6851004810c0836600545b0b83a28a30dbee37f4d961057b4259bfd4244fbbeb614867fc06ecd7e963c320a06c338f14c0e1673ce072a6f23eddbfdd2d77e497f4d04b47802ecee8e2b19cb0fbefe84c6f713b25e08a662dd130a35495e1c898e92f543967c79c30b856678b21c216a0a5b858bcf1bcbf4a960273b065163ea3ccdca4c0f5df6bee72c04d32284ea21331c6b84c44ee156cb", - "priv": "fa0863ac874ddb903e97b70d9ddadab5f53be7e9cf8180f800fccecb487492ca4018a09f2d3720d23232732e3f7b58e918e5eeedd8099fd7eb33c3e52e18cc607da89d99666577da7ce56104e4a2398ec2e3a2019d39fc070e585787c655330995f49044796a9502725ba0d4a8509aa7cc5b14a36fbeea0948e1ce8394d902e302326c08c84ccb267224498dd1b28559264d528008a0b4601843904b00289b2805d4c84de2944009386c21c188c8806421b40d62184503a48490c444c3b62452c24940b285092041413830c0326482b408d8b608d1c429494885c0a004d0c07120360d94404a0a3112a3827199008a4940610b47044b885098486524b18c18b6441b462ce09005d8c60961220c88187120a62014336a11806d83002983004ce4a4045bb028d2086920265100b620d210640211288ba241cc220d0a489158b468808850520010018089992489613202da9448931632188709e4b80cd3322289161283042c00b8055b886542b84ca4162a4ab80081c28c5c4840084265e2384c4ba4309a942d19268d54420a9a126e1c04249b4444e4986c92c690149565d314225180402014200207621a423144367180468243b20c42400c0c294e894285e2380859084ed84265a4348e000051e2088c5888911a36865bc0281cb3610c206888a04420028c202989182382594448d44840a342254c0240e138861b46645c12300b45450a354ad2a88102868900852dc438864b368a13a25023b65112332a0a334924158523b35150168111266d911684d9140e0940222332860125460ca9310020511c82805b90280bc0000a2304e1342852386010b2442397101144119824204336885a302088b61014a240a4b86108996918122c18894018920c42b0215ca269c2204460428cd286049c2485dba84c13334a08b690410249db902c081732d91041e0480413c78d9c34858a10711412808b182d54460d02a4700003494aa24961c605c44248cb3850cca00100b12c0a012501a91052200c0c224003a62988b82c4a941001c520cb188001447043026aa488819a903003258e4c420198b46953b4018cc46912308411c1110904704c440422a421dbc831984211d9b261090146c0380de00852dab6695312094c188610a749cb385118022004c40d5c904189a691c1082ee2400863b0302019895aa48858288a52382dd094698a264e0002698202619c30098b886c110210a4b08052188e18358a44264422856112b8684016860c01614006040a834588081154905064028ed14440dc1461a1281098164d14383203086944388c4224125414052407284cc488cc442144a8841b8824d9428ad346289a440dc4266222a449dcb2511b1026da022421a62ddb0025213066c9404c2193710386900c2210a434850191310b44300ac5480426491ac670034201439608ca1469c802258334064286908944254a862ca336125c182e49084242304ec9b69190b82064386609c8704c440002b531da148d22c2241927000202928ca80c6096649b088e9ab2458bb065818451a3284512358d20c9880442691a922c92b844da4651d9426183a07123052cdc944903256c94168d5108650a91851c260d83144a5c382813458504c8855a1852d9b6101106220c28311b8469613849a2a65102b6698c980524037293186ec9c48523306cca442d0c0340d08685ca268d98460a1c122c09278184106a14a66d90464cd94229cbc650cb160d12c32583308d83088904295009c921a2b80cdc964c8022829c1828dcc02151948112816d0c420ae0302a4bb84924a8880b306459a84160a20113c92c5216624a440921330d99880844286a02218049c481e1346153166cd4141164a81022c1504ca4400aa84408172ad88409211260d10084ca340c80a229d91646a0189261004cd8444602426240843020037043426edb1088ccc88581a885d8346921c49093c020caa040a1183024495121c02190a26c08c5101019929428899b48841819488a188214b5051817401b46904912488b021002b5501844890a2031233049131748a0b48c1ca94882a07123280c9cb8448938659a2404c08084e0404dc49088dc243223244e080660231300c3087201936c54a65024278a1b338c93228020236e1c1980d40608148720a22400a31489db30864b8824d88844d1305211800121886812b421541844b84b22d554149f023e1d3dc5b2ae9a0ea4b0662dde57cc0c76ff2018e3111abd3b0e6a27d2bc412088bd162dac9efe8c54c85b93391ad0845d471aaf31d7bd916c858cb7207d837f253e448b4b6bc66cef8f6fb0b68fea3798cc19684e6e1ddca43add9d13b27ae4e799b4823920ba874f21072f3c9c347838962e4d39ec5a72243e74bb9b28e6cdc19017c14b3338c4d66e2768ab9c34f64c6bee0db13fb401d11322df633ed721b4deacb6da6f1fcdd84729c8648c3ce155a6689524c6968d54fecd6dc1dcaf84460abd754edc0c481500b72007492e4e8698ff489dfc7abff69b58b92217866893f22eae115be03938444a927c0a718fc356f35a90da014e7a00cd3b825dd5f21675e8f45af72bb4dcc87715a84b41a8ce53f1bb6c7ac9117c060cf1d79db8c169b1a83d068892d809e4eb70cc85925c1c1c15f7fd15f3976d5e68217dd45ff41562d6bd709c485cde25e40e2bfc929dab157059b34b3c536cffd033e0737416e2d9cd4eda27ed7a1f3966d02822aead964dab2b519987b721b4f932cbb7fa046d13ff23484e710a2eadc9b0dc5e48cb45c60b79d12e99958cc33d5001c950b97a17b376b6b66250a72e9dc5c38bab71809a4acdee0edb727d909647e0994502149c70f1e4e970155c86693e570535a4744fdb8b7516fcf3fb3e96bcb0cb81cf36cb8c0ea41e94f745a67ae210cf4ddfe64ba5b570eacc685d4df35359b2c48d0c080da87a41ec4808d42b20cc5ace65d66b6798df39f2cccc3d49afff4132d00d2cff9f0cd01ddf14ae61a551b992062b3e48abea60cdab3e0106b5b5c13da96f3199042df4d076e507c0016396d5ab862e809d593550c22c2cec1a2f14a7218e1fbfd6e8f29bae700fe55827e4328b99041e52df2f681ce9d09c9815a75e1f4723a70f7907c683fe8ae256d53cf637ce036e43cd6f28cd07e88756ae8a9d9d8b39fb9f9699f0aca76ec8e7b9e85459323fb132be8569ac7b3b8a2b758d8937b05941d698b47237d1830212d3b5fb0522462ed1e4511c6df04aad5cb763eaac1a59f04ad09b1181f592f1b977b03a8e65ec3d82843d758e1f4053f4d759c2a3142c8a07079d98d218016dcef9d5d4d367657de5b659a6bacdff9c76e98cfca80809370c2d4e7e2c31f682e549cdf70424e16532ed4020433df7ec5355d8706c5fd6840dd3393120d1d379b8b6d35655644f03e24535ede9adb6319d9563410bd1d47c0bc7ca7607e6bd13a879dcbd7b3ab789639d563ec074afb7a958257ff5c15a8ab95acd99fdaa614dc502c1c691ba6a81e1cfea6e3e8633282b8c99fd0e5d72e6057ff342ad184bdd014d4b6021b4c7181b4e979bf1e4e05e00a5c86aa10c0bdc5cc66aad4cafd25fdc50c78e3cec127a393d81318264398e6d87879f80e3cea2bb5d4966222c3a1a9f59af7f8106231be7125ed56b585c55b827d21f4169b6800de94b680c7dea3a435e07c2bb918dea94bfd592969c10d5ee08b8456b64aadec0b5ab93d23cffc7c0e0a28899b1ee1e517ce155a1f0715ec988379dcc9d43c6746437435804cf7660f3c7ea6d820a536cc0d22f6e34016a361754551d588b8ab06274a7061d7002d2e99798c30e785f759359607b89beafca07651a611dbe8d8bed2ccaf0d32d119cc03ae92522cc5886731192c8ee199094179e164b52e285a6a0af8ed3105f96e9e9777929e6adc1798e5d2785b24bfb0f1b5450fd2f920fe72e4736343a1a1564777f582d5238b76d00c45e65b7fd98b65cb8a673792a7833b8896a08c7c3617ab1abb90ebdf441c558db295c420ca4a36176bc339dc88f3f84f2b4397fdc1b8020a0b0043a65cde6bc94ffc4d3078485b2c505de2b732aa289b913057fd047caf9c26dfb12b5993ade6fbeff3dcb5ed633549f2d41a5acbb46aba65ba9410879d852791df2512979dcdddd300cde9c42d3dcfa93e15df8d09178e1f38b75e55246b493207e90acc8569f02796f6eaa4964444edfbfa106ea4f2b0945f5f89598c459df00b08ab31b9a425b5b177c486514a1a68f13981968cc466aa751fa5fa66e24c022ea344e0393e1df785904e4ba9171d26b86e50322d04a89ad8808c178e8bbe70790bffd2abc7cede4b08383b812455257830c0388298a1589c3720e631c298f3b625ce484a670961e5f36bb9d1ded900b0f89993403750c4e524eb2f7e860566b65f269428d9a1eda1a4dcfc3fc364971c10acadb7ab20c4bf23023a668c96cf329d367e651466b7c4daff39babef19fb195c71b2a453d19e7f4d9df7f1b8c8ca913dfaeb34475e285298ee890fecdf7880c278c287f8895d8013fcbdf3da5f9ed755e7c37381a6c6b3aae225a96062b1fd97e43ba6ffcc5ccc48b730b34c4cafbecf945a7c7902d8339b0fbe08c2208436e07709df9545a24985cd487ef0a541e6f5da205ae17281f6f743070fcfe53115c72b3adc07cdf0a447870425b44914d492b06eab2d81225929964284827cd2ffb47965dca0443995a2cafc01d2676979aa941d7d15a1e843e54d3f2b2fbc55fd8912573d124ef52c937d0489a9912656eec5b1afee0225b67aeabd6eec14f894deba7a3b9922462ade265eecd97d022029b5263d010351f061400846780936ad5779b7caeeebae61ff6fe87214140035f3e49c005bbb845d5058bd64e30cfa8b347d51792c4ab2af9ec028907295426b19016d8777313dd4ee16d346979ea9ae411025e55e76b18fa230f6fea85c36d7cd18904e44046944582fabd7ad439678e420032a9e8140c9dfb0e419f651fc833068f266185ee8696ef6abea55a847386165149a4e6ca3f80ce718a1a4a87cd4e7b49fd2aee1cdc935d59607941fb6147efcfbf070b79e2a1fb45cceb5d178b537e8c3348dbf2ff5aa24396d4d4686575a52ad934e084addc3ee411dc1b7e2cedb542a79304e81d92e58a198613e303d0fbe2bfc830880658a8c6edfae564526b7efbf2aa8d7922cbe8fca149c70511ea02294e2da9ceddc4caa90689f705cd1609f1568fb395f707003e7dcd25178d00df7ffd8a3ebfcce5e39dcecc74db1835743b7bbb0b93a67b8c0e4ae7e42bbedd46e01d3b39fe1ed142cbcc75113456208c8e9c687c4baf48a4ec06c4577e435c8f2b31504e5d18103330a6151dc72a4299e316f1cd243bec42c5efaeabf40922062065b87577def72b8c1702a35485bb992b9f0e41816a5b0c5f15d1a19546b3a3619cd14325f6afffbed220b70917e15833bcd729b3d43de88ca98d72ddea110eb2e9bc69012aa150d77767df3adf710dbd3df1b8bbd600093a1935b158d08390fdabf187922d9af20004ea9dc70b0dcfaa03a45056aa32704760afa5541ee7c9de66784b72a62e5e6f0336f496f4ca34773ca4d69c654936bcbf33bdea1c1d7118afcc9b4f7476ce1e705391e0f428a136e23dfd99f0a1d8552b952feb3aae8a578a997a3f1834aca68f45d381b6a551fe770f37e169bd354cdc258948b66ec8374faa6f5e8971e8e6832cf79d90a018792fa87dab68c4e8d6fa0263a9ee55ccb96ebc832d9027902075c4950839eb6f988a8ced0ad33fba4e9775ef4483f635a9277a924b8e699937327e126eeb108f8deab4a3513096320d4b2076ccfcfcf79b12356cfa27ee5da8ecfdbba8d6346f99e2d95b338d578b847c5ac916d0e3e9c808d8ec25bb1279fef5fa010f0dea9ef54816a754e5e1fbc30d049f36c797ef918cea785ead790af64398a88a25f2d561c8b5987cee11ec854848fffa90b73c07e08b1234d91ed9ccca9e0cbbb122ca9dcb903a847f847e80d37810bec95f0859293fd035691fc7e28308c2c4c4e78ff84f66f84349afc8447f80d7343ac90b8cc4a5aef43473f972d050af10b868c2f36bad230caf28f12e08e1a2491713c1278163281c63225ddea6668cbdb4c2e8ae734f860d73f6e204dd8f20601b4508f772c75b5c623b2d0dc67eeb7226c5a080320deec0883f5504827a3624aa813c9e6480d96e57f108b0d4abf27d53cfc183515aa759b7b707e8dd5c44dd6c01385423efb5bc0f644f2e0507859a05493ae4f96c479f5984fc008e44ca18ca7742508a0f0816e81fd8bc31e26cdd0672569a6c3166e3ec3b7305d09a2cdf452794d896aadfdd053a3421507a54e43ec7181b976155869fa53113e936ceed685a6e70a12e163727580d5d15ff0e6989c5a0c7872ea25807132226deddb069317403508b0b9f47f1df4026543d66b1ed5689635f04caa2784b9d41d9a5d1c89afc220d3defa70a8a24ad42d1a68641d804a74db215b0cd1ad9a6944553192a8f9e45fc8f96cb4bdedb4c5db74d3e446eeb06018d01b4a063606d05365bb26e1557d7e651140cc34241c435fead6a6edfd4334f3c3a316bc61dae7c91d8edfff4b8ee9612eeb5fb4265a70c95b9c36643946ecd287f73ea279491e36abca6e8d1af3929be436122c56a08133f874bcab54014480097baecc910bb53d69d9dbbc5687c47a5add71acc31e2513f20e0def47c48d3c27a46778514979dbc3c4878a5338b480bfbd8e1043febc97110b3b03d74a6065a18f2b24a98df24b4579e5048180ada0256cc0ed50048db4b04dfdc143988ea207a415a998bf890ef16edd4b6dd4c50a0180dd898c77eefede80ca905805f1dafafcd94c3ff7a4221336e404a743b7a484b328458f25dca7abf19bf6b709547956a19966" - } - ] -} \ No newline at end of file diff --git a/scripts/vendor-boringssl.sh b/scripts/vendor-boringssl.sh index a213ece35..e6ebd3bd3 100755 --- a/scripts/vendor-boringssl.sh +++ b/scripts/vendor-boringssl.sh @@ -346,8 +346,6 @@ cat << EOF > "$DSTROOT/include/CCryptoBoringSSL.h" #include "CCryptoBoringSSL_hrss.h" #include "CCryptoBoringSSL_md4.h" #include "CCryptoBoringSSL_md5.h" -#include "CCryptoBoringSSL_mldsa.h" -#include "CCryptoBoringSSL_mlkem.h" #include "CCryptoBoringSSL_obj_mac.h" #include "CCryptoBoringSSL_objects.h" #include "CCryptoBoringSSL_opensslv.h" From 993467897d0c6250bfb542e3334f4050ca745f72 Mon Sep 17 00:00:00 2001 From: Fabrice de Gans Date: Mon, 21 Jul 2025 12:36:27 -0700 Subject: [PATCH 12/36] build: Make swift-crypto build on Windows (#370) Make swift-crypto build on Windows ### Checklist - [X] I've run tests to see all new and existing tests pass - [X] I've followed the code style of the rest of the project - [X] I've read the [Contribution Guidelines](CONTRIBUTING.md) - [X] I've updated the documentation if necessary #### If you've made changes to `gyb` files - [N/A] I've run `.script/generate_boilerplate_files_with_gyb` and included updated generated files in a commit of this pull request ### Motivation: Currently, swift-crypto on the main branch does not build on Windows. ### Modifications: * Add the Windows Arm64 assembly files to the CMake build. * Add appropriate CMake options for swift-crypto to build on Windows. ### Result: swift-crypto can be built on Windows from main Fixes #369 --------- Co-authored-by: Cory Benfield --- CMakeLists.txt | 16 ++++++++++++++++ Sources/CCryptoBoringSSL/CMakeLists.txt | 21 ++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18bed6aaf..f05387047 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,10 @@ cmake_minimum_required(VERSION 3.15.1) +if(POLICY CMP0157) + cmake_policy(SET CMP0157 NEW) +endif() + project(SwiftCrypto LANGUAGES ASM C CXX Swift) @@ -47,6 +51,18 @@ if(CMAKE_SYSTEM_NAME STREQUAL Darwin AND NOT CMAKE_CROSSCOMPILING) set(CMAKE_RANLIB "/usr/bin/ranlib") endif() +set(CMAKE_CXX_STANDARD 17) +if(CMAKE_SYSTEM_NAME STREQUAL Windows) + # We need to ensure that we don't include the min/max macros from the Windows SDK. + add_compile_definitions(NOMINMAX) + # We can only link against the DLL version of the MSVC runtime library for now. + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") + if(CMAKE_Swift_COMPILER_VERSION VERSION_EQUAL 0.0.0 OR CMAKE_Swift_COMPILER_VERSION VERSION_GREATER_EQUAL 6.2) + # We need to set the static library prefix to "lib" so that we can link against the static libraries. + set(CMAKE_STATIC_LIBRARY_PREFIX_Swift "lib") + endif() +endif() + if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin) find_package(dispatch CONFIG) find_package(Foundation CONFIG) diff --git a/Sources/CCryptoBoringSSL/CMakeLists.txt b/Sources/CCryptoBoringSSL/CMakeLists.txt index fe17a4184..9da329bd4 100644 --- a/Sources/CCryptoBoringSSL/CMakeLists.txt +++ b/Sources/CCryptoBoringSSL/CMakeLists.txt @@ -342,8 +342,27 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Linux|Android|FreeBSD|OpenBSD" AND CMAKE_SYSTE gen/bcm/vpaes-armv8-linux.S gen/crypto/chacha-armv8-linux.S gen/crypto/chacha20_poly1305_armv8-linux.S) +elseif(CMAKE_SYSTEM_NAME MATCHES "Windows" AND CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|amd64|x86_64") + target_sources(CCryptoBoringSSL PRIVATE +) +elseif(CMAKE_SYSTEM_NAME MATCHES "Windows" AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|arm64|aarch64") + target_sources(CCryptoBoringSSL PRIVATE + gen/bcm/aesv8-armv8-win.S + gen/bcm/aesv8-gcm-armv8-win.S + gen/bcm/armv8-mont-win.S + gen/bcm/bn-armv8-win.S + gen/bcm/ghash-neon-armv8-win.S + gen/bcm/ghashv8-armv8-win.S + gen/bcm/p256-armv8-asm-win.S + gen/bcm/p256_beeu-armv8-asm-win.S + gen/bcm/sha1-armv8-win.S + gen/bcm/sha256-armv8-win.S + gen/bcm/sha512-armv8-win.S + gen/bcm/vpaes-armv8-win.S + gen/crypto/chacha-armv8-win.S + gen/crypto/chacha20_poly1305_armv8-win.S) else() - message(FATAL_ERROR "platform sources are not defined here") + message(FATAL_ERROR "platform sources are not defined here for ${CMAKE_SYSTEM_NAME} on ${CMAKE_SYSTEM_PROCESSOR}") endif() target_include_directories(CCryptoBoringSSL PUBLIC From 88b9c9b3b7f0f5d1fcbc682dba50881ab77de087 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Tue, 22 Jul 2025 14:31:55 +0100 Subject: [PATCH 13/36] Work around Swift compiler issue with consuming and TSAN (#384) This patch works around the absence of a fix for https://github.com/swiftlang/swift/pull/76186 on older Swift compilers. --- .../EC/EllipticCurvePoint.swift | 113 ++++++++++++++++++ .../_CryptoExtras/Util/Data+Extensions.swift | 5 + 2 files changed, 118 insertions(+) diff --git a/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift b/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift index 266886237..b2c813834 100644 --- a/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift +++ b/Sources/CryptoBoringWrapper/EC/EllipticCurvePoint.swift @@ -69,6 +69,10 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.multiply(by: rhs, on: group, context: context) } + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) @usableFromInline package consuming func multiplying( by rhs: ArbitraryPrecisionInteger, @@ -78,6 +82,18 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.multiply(by: rhs, on: group, context: context) return self } + #else + @usableFromInline + package func multiplying( + by rhs: ArbitraryPrecisionInteger, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> EllipticCurvePoint { + var `self` = self + try self.multiply(by: rhs, on: group, context: context) + return self + } + #endif @usableFromInline package static func multiplying( @@ -110,6 +126,10 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.add(rhs, on: group, context: context) } + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) @usableFromInline package consuming func adding( _ rhs: consuming EllipticCurvePoint, @@ -119,7 +139,23 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.add(rhs, on: group, context: context) return self } + #else + @usableFromInline + package func adding( + _ rhs: consuming EllipticCurvePoint, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> EllipticCurvePoint { + var `self` = self + try self.add(rhs, on: group, context: context) + return self + } + #endif + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) @usableFromInline package static func adding( _ lhs: consuming EllipticCurvePoint, @@ -130,6 +166,19 @@ package struct EllipticCurvePoint: @unchecked Sendable { try lhs.add(rhs, on: group, context: context) return lhs } + #else + @usableFromInline + package static func adding( + _ lhs: EllipticCurvePoint, + _ rhs: EllipticCurvePoint, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> EllipticCurvePoint { + var lhs = lhs + try lhs.add(rhs, on: group, context: context) + return lhs + } + #endif @usableFromInline package mutating func invert( @@ -150,6 +199,10 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.invert(on: group, context: context) } + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) @usableFromInline package consuming func inverting( on group: BoringSSLEllipticCurveGroup, @@ -158,7 +211,22 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.invert(on: group, context: context) return self } + #else + @usableFromInline + package func inverting( + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> EllipticCurvePoint { + var `self` = self + try self.invert(on: group, context: context) + return self + } + #endif + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) @usableFromInline package static func inverting( _ point: consuming EllipticCurvePoint, @@ -168,6 +236,18 @@ package struct EllipticCurvePoint: @unchecked Sendable { try point.invert(on: group, context: context) return point } + #else + @usableFromInline + package static func inverting( + _ point: EllipticCurvePoint, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> EllipticCurvePoint { + var point = point + try point.invert(on: group, context: context) + return point + } + #endif @usableFromInline package mutating func subtract( @@ -190,6 +270,10 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.subtract(rhs, on: group, context: context) } + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) @usableFromInline package consuming func subtracting( _ rhs: consuming EllipticCurvePoint, @@ -199,7 +283,23 @@ package struct EllipticCurvePoint: @unchecked Sendable { try self.subtract(rhs, on: group, context: context) return self } + #else + @usableFromInline + package func subtracting( + _ rhs: EllipticCurvePoint, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> EllipticCurvePoint { + var `self` = self + try self.subtract(rhs, on: group, context: context) + return self + } + #endif + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) @usableFromInline package static func subtracting( _ rhs: consuming EllipticCurvePoint, @@ -210,6 +310,19 @@ package struct EllipticCurvePoint: @unchecked Sendable { try lhs.subtract(rhs, on: group, context: context) return lhs } + #else + @usableFromInline + package static func subtracting( + _ rhs: EllipticCurvePoint, + from lhs: EllipticCurvePoint, + on group: BoringSSLEllipticCurveGroup, + context: FiniteFieldArithmeticContext? = nil + ) throws -> EllipticCurvePoint { + var lhs = lhs + try lhs.subtract(rhs, on: group, context: context) + return lhs + } + #endif @usableFromInline package init( diff --git a/Sources/_CryptoExtras/Util/Data+Extensions.swift b/Sources/_CryptoExtras/Util/Data+Extensions.swift index 10494a8fb..87ac84ffb 100644 --- a/Sources/_CryptoExtras/Util/Data+Extensions.swift +++ b/Sources/_CryptoExtras/Util/Data+Extensions.swift @@ -15,9 +15,14 @@ import Foundation extension Data { + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) // This overload reduces allocations when used in a chain of infix operations. static func + (lhs: consuming Data, rhs: consuming Data) -> Data { lhs.append(contentsOf: rhs) return lhs } + #endif } From 84b1d494118d63629a785230135f82991f02329e Mon Sep 17 00:00:00 2001 From: George Barnett Date: Tue, 22 Jul 2025 15:05:35 +0100 Subject: [PATCH 14/36] Add a few more inlinability annotation (#383) Motivation: Version 3.13.0 hits a compiler assertion when compiling in release mode on Linux with Swift 6.1. This appears to stem from missing inlinable annotations. Modifications: - Add a few more `@inlinable` and `@usableFromInline` annotations Result: Builds on 6.1+ in release mode --- Sources/Crypto/Util/SecureBytes.swift | 38 ++------------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/Sources/Crypto/Util/SecureBytes.swift b/Sources/Crypto/Util/SecureBytes.swift index 71b6dfe16..2efb994aa 100644 --- a/Sources/Crypto/Util/SecureBytes.swift +++ b/Sources/Crypto/Util/SecureBytes.swift @@ -21,15 +21,12 @@ private let emptyStorage:SecureBytes.Backing = SecureBytes.Backing.createEmpty() @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) struct SecureBytes { - @usableFromInline var backing: Backing - @inlinable init() { self = .init(count: 0) } - @usableFromInline init(count: Int) { if count == 0 { self.backing = emptyStorage @@ -43,7 +40,6 @@ struct SecureBytes { } /// Allows initializing a SecureBytes object with a closure that will initialize the memory. - @usableFromInline init(unsafeUninitializedCapacity: Int, initializingWith callback: (inout UnsafeMutableRawBufferPointer, inout Int) throws -> Void) rethrows { self.backing = Backing.create(capacity: unsafeUninitializedCapacity) try self.backing._withVeryUnsafeMutableBytes { veryUnsafePointer in @@ -59,7 +55,6 @@ struct SecureBytes { @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension SecureBytes { - @inlinable mutating func append(_ data: C) where C.Element == UInt8 { let requiredCapacity = self.count + data.count let backingCapacity = self.backing.allocatedCapacity @@ -71,7 +66,6 @@ extension SecureBytes { self.backing._appendBytes(data) } - @usableFromInline mutating func reserveCapacity(_ n: Int) { let backingCapacity = self.backing.allocatedCapacity if backingCapacity >= n { @@ -95,32 +89,27 @@ extension SecureBytes: Equatable { // MARK: - Collection conformance @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension SecureBytes: Collection { - @usableFromInline @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) struct Index { - /* fileprivate but usableFromInline */ @usableFromInline var offset: Int + /* fileprivate but usableFromInline */ var offset: Int - /*@inlinable*/ @usableFromInline internal init(offset: Int) { + /*@inlinable*/ internal init(offset: Int) { self.offset = offset } } - @inlinable var startIndex: Index { return Index(offset: 0) } - @inlinable var endIndex: Index { return Index(offset: self.count) } - @inlinable var count: Int { return self.backing.count } - @inlinable subscript(_ index: Index) -> UInt8 { get { return self.backing[offset: index.offset] @@ -130,7 +119,6 @@ extension SecureBytes: Collection { } } - @inlinable func index(after index: Index) -> Index { return index.advanced(by: 1) } @@ -139,7 +127,6 @@ extension SecureBytes: Collection { // MARK: - BidirectionalCollection conformance @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension SecureBytes: BidirectionalCollection { - @inlinable func index(before index: Index) -> Index { return index.advanced(by: -1) } @@ -156,7 +143,6 @@ extension SecureBytes: MutableCollection { } // MARK: - RangeReplaceableCollection conformance @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension SecureBytes: RangeReplaceableCollection { - @inlinable mutating func replaceSubrange(_ subrange: Range, with newElements: C) where C.Element == UInt8 { let requiredCapacity = self.backing.count - subrange.count + newElements.count let backingCapacity = self.backing.allocatedCapacity @@ -182,7 +168,6 @@ extension SecureBytes: RangeReplaceableCollection { } // The default implementation of this from RangeReplaceableCollection can't take advantage of `ContiguousBytes`, so we override it here - @inlinable public mutating func append(contentsOf newElements: Elements) where Elements.Element == UInt8 { let done:Void? = newElements.withContiguousStorageIfAvailable { replaceSubrange(endIndex..(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T { return try self.backing.withUnsafeBytes(body) } - @inlinable mutating func withUnsafeMutableBytes(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T { if !isKnownUniquelyReferenced(&self.backing) { self.backing = Backing.create(copying: self.backing) @@ -213,7 +196,6 @@ extension SecureBytes: ContiguousBytes { return try self.backing.withUnsafeMutableBytes(body) } - @inlinable func withContiguousStorageIfAvailable(_ body: (UnsafeBufferPointer) throws -> R) rethrows -> R? { return try self.backing.withContiguousStorageIfAvailable(body) } @@ -222,7 +204,6 @@ extension SecureBytes: ContiguousBytes { // MARK: - DataProtocol conformance @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension SecureBytes: DataProtocol { - @inlinable var regions: CollectionOfOne { return CollectionOfOne(self) } @@ -257,37 +238,29 @@ extension SecureBytes.Index: Strideable { // MARK: - Heap allocated backing storage. @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension SecureBytes { - @usableFromInline @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) internal struct BackingHeader { - @usableFromInline internal var count: Int - @usableFromInline internal var capacity: Int } - @usableFromInline @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) internal class Backing: ManagedBuffer { - @usableFromInline class func createEmpty() -> Backing { return Backing.create(minimumCapacity: 0, makingHeaderWith: { _ in BackingHeader(count: 0, capacity: 0) }) as! Backing } - @usableFromInline class func create(capacity: Int) -> Backing { let capacity = Int(UInt32(capacity).nextPowerOf2ClampedToMax()) return Backing.create(minimumCapacity: capacity, makingHeaderWith: { _ in BackingHeader(count: 0, capacity: capacity) }) as! Backing } - @usableFromInline class func create(copying original: Backing) -> Backing { return Backing.create(bytes: original) } - @inlinable class func create(bytes: D) -> Backing { return bytes.withUnsafeBytes { bytesPtr in let backing = Backing.create(capacity: bytesPtr.count) @@ -300,7 +273,6 @@ extension SecureBytes { } } - @usableFromInline class func create(randomBytes: Int) -> Backing { let backing = Backing.create(capacity: randomBytes) backing._withVeryUnsafeMutableBytes { targetPtr in @@ -320,7 +292,6 @@ extension SecureBytes { } } - @usableFromInline var count: Int { get { return self.header.count @@ -330,7 +301,6 @@ extension SecureBytes { } } - @usableFromInline subscript(offset offset: Int) -> UInt8 { get { // precondition(offset >= 0 && offset < self.count) @@ -346,7 +316,6 @@ extension SecureBytes { @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension SecureBytes.Backing { - @usableFromInline var allocatedCapacity: Int { #if os(OpenBSD) return self.header.capacity @@ -419,7 +388,6 @@ extension SecureBytes.Backing { /// Moves the range of bytes identified by the slice by the delta, crashing if the move would /// place the bytes out of the storage. Note that this does not update the count: external code /// must ensure that that happens. - @usableFromInline /* private but usableFromInline */ func _moveBytes(range: Range, by delta: Int) { // We have to check that the range is within the delta, as is the new location. precondition(range.lowerBound >= 0) @@ -437,7 +405,6 @@ extension SecureBytes.Backing { } // Copies some bytes into the buffer at the appropriate place. Does not update count: external code must do so. - @inlinable /* private but inlinable */ func _copyBytes(_ bytes: C, at offset: Int) where C.Element == UInt8 { precondition(offset >= 0) precondition(offset + bytes.count <= self.allocatedCapacity) @@ -470,7 +437,6 @@ extension SecureBytes.Backing: ContiguousBytes { } /// Very unsafe in the sense that this points to uninitialized memory. Used only for implementations within this file. - @inlinable /* private but inlinable */ func _withVeryUnsafeMutableBytes(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T { let capacity = self.allocatedCapacity From 64a4de00fb65d97d68420ac908ba3962dfb97017 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Wed, 30 Jul 2025 12:45:10 +0100 Subject: [PATCH 15/36] Add some benchmarks for EC key agreement (#390) We should have some benchmarks for EC key agreement. --- Benchmarks/Benchmarks/Benchmarks.swift | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Benchmarks/Benchmarks/Benchmarks.swift b/Benchmarks/Benchmarks/Benchmarks.swift index b7e2d241d..b9b5ad55c 100644 --- a/Benchmarks/Benchmarks/Benchmarks.swift +++ b/Benchmarks/Benchmarks/Benchmarks.swift @@ -158,4 +158,49 @@ let benchmarks = { blackHole(try privateKey.evaluate(blindedElement)) } } + + Benchmark( + "key-exchange-p256", + configuration: Benchmark.Configuration( + metrics: defaultMetrics, + scalingFactor: .kilo, + maxDuration: .seconds(10_000_000), + maxIterations: 10 + ) + ) { benchmark in + for _ in benchmark.scaledIterations { + let (key1, key2) = (P256.KeyAgreement.PrivateKey(), P256.KeyAgreement.PrivateKey()) + blackHole(try key1.sharedSecretFromKeyAgreement(with: key2.publicKey)) + } + } + + Benchmark( + "key-exchange-p384", + configuration: Benchmark.Configuration( + metrics: defaultMetrics, + scalingFactor: .kilo, + maxDuration: .seconds(10_000_000), + maxIterations: 10 + ) + ) { benchmark in + for _ in benchmark.scaledIterations { + let (key1, key2) = (P384.KeyAgreement.PrivateKey(), P384.KeyAgreement.PrivateKey()) + blackHole(try key1.sharedSecretFromKeyAgreement(with: key2.publicKey)) + } + } + + Benchmark( + "key-exchange-p521", + configuration: Benchmark.Configuration( + metrics: defaultMetrics, + scalingFactor: .kilo, + maxDuration: .seconds(10_000_000), + maxIterations: 10 + ) + ) { benchmark in + for _ in benchmark.scaledIterations { + let (key1, key2) = (P521.KeyAgreement.PrivateKey(), P521.KeyAgreement.PrivateKey()) + blackHole(try key1.sharedSecretFromKeyAgreement(with: key2.publicKey)) + } + } } From 176abc28e002a9952470f08745cd26fad9286776 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Wed, 30 Jul 2025 12:53:08 +0100 Subject: [PATCH 16/36] Cache curves to avoid repeatedly reallocating state (#391) Motivation We shouldn't repeatedly reconstruct static data Modifications - Turn the groups into static lets instead of computed properties Result Fewer allocations --- .../EC/BoringSSL/NISTCurvesKeys_boring.swift | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Sources/Crypto/Keys/EC/BoringSSL/NISTCurvesKeys_boring.swift b/Sources/Crypto/Keys/EC/BoringSSL/NISTCurvesKeys_boring.swift index fc7d7bdcd..f259fada4 100644 --- a/Sources/Crypto/Keys/EC/BoringSSL/NISTCurvesKeys_boring.swift +++ b/Sources/Crypto/Keys/EC/BoringSSL/NISTCurvesKeys_boring.swift @@ -36,26 +36,20 @@ extension OpenSSLSupportedNISTCurve { @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension P256: OpenSSLSupportedNISTCurve { - @inlinable - static var group: BoringSSLEllipticCurveGroup { - try! BoringSSLEllipticCurveGroup(.p256) - } + @usableFromInline + static let group = try! BoringSSLEllipticCurveGroup(.p256) } @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension P384: OpenSSLSupportedNISTCurve { - @inlinable - static var group: BoringSSLEllipticCurveGroup { - try! BoringSSLEllipticCurveGroup(.p384) - } + @usableFromInline + static let group = try! BoringSSLEllipticCurveGroup(.p384) } @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) extension P521: OpenSSLSupportedNISTCurve { - @inlinable - static var group: BoringSSLEllipticCurveGroup { - try! BoringSSLEllipticCurveGroup(.p521) - } + @usableFromInline + static let group = try! BoringSSLEllipticCurveGroup(.p521) } @usableFromInline From 8c9d27a3398e82887d360aa7fd922a4b5dd10b03 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 30 Jul 2025 15:13:18 +0100 Subject: [PATCH 17/36] Enable release mode builds in CI (#388) Enable release mode build tests in CI ### Motivation: Some errors do not show up in debug builds. Enabling release mode builds improves the CI coverage. ### Modifications: Add a new workflow for release mode builds and enable it in the pull requests workflow. ### Result: The CI performs release mode builds to test pull requests. --------- Co-authored-by: George Barnett --- .github/workflows/main.yml | 9 +++++++++ .github/workflows/pull_request.yml | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d06fb81f5..9e537d8b8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,6 +25,15 @@ jobs: windows_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" + release-builds: + name: Release builds + uses: apple/swift-nio/.github/workflows/release_builds.yml@main + with: + windows_6_0_enabled: true + windows_6_1_enabled: true + windows_nightly_next_enabled: true + windows_nightly_main_enabled: true + cxx-interop: name: Cxx interop uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 4496559bd..234445829 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -30,6 +30,15 @@ jobs: windows_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" + release-builds: + name: Release builds + uses: apple/swift-nio/.github/workflows/release_builds.yml@main + with: + windows_6_0_enabled: true + windows_6_1_enabled: true + windows_nightly_next_enabled: true + windows_nightly_main_enabled: true + cxx-interop: name: Cxx interop uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main From c68a7a7c7f7316107c9b69378d1734f590552f7b Mon Sep 17 00:00:00 2001 From: Wojciech Nagrodzki <278594+wnagrodzki@users.noreply.github.com> Date: Thu, 31 Jul 2025 14:06:20 +0200 Subject: [PATCH 18/36] Add Sequence conformance to AES._CBC.IV (#389) (#392) Add Sequence conformance to `AES._CBC.IV` where `Element` is `UInt8`. ### Checklist - [ ] I've run tests to see all new and existing tests pass > PKCS8DERRepresentationTests do not compile on master branch with Error `'pkcs8DERRepresentation' is only available in iOS 14.0 or newer`. All the other tests pass after my changes. - [x] I've followed the code style of the rest of the project - [x] I've read the [Contribution Guidelines](CONTRIBUTING.md) - [x] I've updated the documentation if necessary #### If you've made changes to `gyb` files - [ ] I've run `.script/generate_boilerplate_files_with_gyb` and included updated generated files in a commit of this pull request ### Motivation: No convenient API for converting `AES._CBC.IV` into `Data`. ### Modifications: Added `Sequence` conformance to `AES._CBC.IV` similarly how it is done for `AES.GCM._SIV.Nonce`. ### Result: It will be possible to create `Data` instance with `AES._CBC.IV` passed as init argument. --------- Co-authored-by: Cory Benfield --- Sources/_CryptoExtras/AES/AES_CBC.swift | 10 +++++++++- Tests/_CryptoExtrasTests/AES_CBCTests.swift | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Sources/_CryptoExtras/AES/AES_CBC.swift b/Sources/_CryptoExtras/AES/AES_CBC.swift index 6d7263a7f..4d1dde8fd 100644 --- a/Sources/_CryptoExtras/AES/AES_CBC.swift +++ b/Sources/_CryptoExtras/AES/AES_CBC.swift @@ -147,8 +147,9 @@ extension AES { extension AES._CBC { /// An initialization vector. @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) - public struct IV: Sendable { + public struct IV: Sendable, Sequence { // AES CBC uses a 128-bit IV. + @usableFromInline var ivBytes: ( UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8 @@ -193,6 +194,13 @@ extension AES._CBC { bytesPtr.copyBytes(from: ivBytes) } } + + @inlinable + public func makeIterator() -> some IteratorProtocol { + withUnsafeBytes(of: ivBytes) { unsafeRawBufferPointer in + Array(unsafeRawBufferPointer).makeIterator() + } + } } } diff --git a/Tests/_CryptoExtrasTests/AES_CBCTests.swift b/Tests/_CryptoExtrasTests/AES_CBCTests.swift index b42131c69..8057562b4 100644 --- a/Tests/_CryptoExtrasTests/AES_CBCTests.swift +++ b/Tests/_CryptoExtrasTests/AES_CBCTests.swift @@ -158,6 +158,14 @@ final class CBCTests: XCTestCase { } } } + + func testToDataConversion() throws { + let randomBytes = (0..<16).map { _ in UInt8.random(in: UInt8.min...UInt8.max) } + let dataIn = Data(randomBytes) + let iv = try AES._CBC.IV(ivBytes: dataIn) + let dataOut = Data(iv) + XCTAssertEqual(dataIn, dataOut) + } } From 334e682869394ee239a57dbe9262bff3cd9495bd Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Tue, 5 Aug 2025 11:16:29 +0100 Subject: [PATCH 19/36] Add AES CMAC support (#394) Motivation AES CMAC is a standardised albeit somewhat uncommon MAC built on top of the AES block cipher. CMAC pops up in a few places, mostly where it is convenient to assume that you have access to AES, but not to a hash function. For example, AES-SIV is built on CMAC. Modifications Add CMAC support Add tests and test vectors Result CMAC is supported --- Sources/_CryptoExtras/AES/CMAC.swift | 200 ++ Sources/_CryptoExtras/CMakeLists.txt | 1 + Tests/_CryptoExtrasTests/CMACTests.swift | 197 ++ .../_CryptoExtrasTests/Utils/BytesUtil.swift | 6 +- Tests/_CryptoExtrasVectors/aes_cmac_test.json | 2842 +++++++++++++++++ 5 files changed, 3245 insertions(+), 1 deletion(-) create mode 100644 Sources/_CryptoExtras/AES/CMAC.swift create mode 100644 Tests/_CryptoExtrasTests/CMACTests.swift create mode 100644 Tests/_CryptoExtrasVectors/aes_cmac_test.json diff --git a/Sources/_CryptoExtras/AES/CMAC.swift b/Sources/_CryptoExtras/AES/CMAC.swift new file mode 100644 index 000000000..08b61e1cd --- /dev/null +++ b/Sources/_CryptoExtras/AES/CMAC.swift @@ -0,0 +1,200 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +@_implementationOnly import CCryptoBoringSSL +import Crypto + +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif + +@available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) +extension AES { + /// A cipher-based message authentication code. + /// + /// CMAC uses AES to implement a MAC. CMAC is useful in contexts where access to + /// a hash function is not guaranteed, but a block cipher will be available. + public struct CMAC: @unchecked Sendable { + // Unchecked sendable because this is CoW. + fileprivate var backing: Backing + + /// Creates a message authentication code generator. + /// + /// Defaults the output size to 128 bits. + /// + /// - Parameters: + /// - key: The symmetric key used to secure the computation. + public init(key: SymmetricKey) throws { + try self.init(key: key, outputSize: 16) + } + + /// Creates a message authentication code generator. + /// + /// - Parameters: + /// - key: The symmetric key used to secure the computation. + /// - outputSize: The number of bytes of MAC to generate. Must be in the range 0 to 16 inclusive. + public init(key: SymmetricKey, outputSize: Int) throws { + guard [128, 192, 256].contains(key.bitCount) else { + throw CryptoError.incorrectKeySize + } + guard (0...16).contains(outputSize) else { + throw CryptoKitError.incorrectParameterSize + } + + self.backing = Backing(key: key, outputSize: outputSize) + } + + /// Adds data to be authenticated by MAC function. This can be called one or more times to append additional data. + /// + /// - Parameters: + /// - bufferPointer: The data to be authenticated. + public mutating func update(bufferPointer: UnsafeRawBufferPointer) { + self.cowIfNeeded() + self.backing.update(bufferPointer) + } + + /// Finalizes the message authentication computation and returns the + /// computed code. + /// + /// - Returns: The message authentication code. + public consuming func finalize() -> AES.CMAC.MAC { + // The combination of "consuming" and "cowifneeded" should + // produce an environment where, if users may choose to + // keep using the MAC, they can, but if they aren't we'll + // avoid an unnecessary CoW. + self.cowIfNeeded() + return self.backing.finalize() + } + + /// Updates the MAC with data. + /// + /// - Parameter data: The data to update the MAC + public mutating func update(data: D) { + for memoryRegion in data.regions { + memoryRegion.withUnsafeBytes { bp in + self.update(bufferPointer: bp) + } + } + } + + private mutating func cowIfNeeded() { + if !isKnownUniquelyReferenced(&self.backing) { + self.backing = Backing(copying: self.backing) + } + } + } +} + +@available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) +extension AES.CMAC { + /// A cipher-based message authentication code. + public struct MAC: MessageAuthenticationCode { + fileprivate let underlyingData: Data + + init(underlyingData: Data) { + self.underlyingData = underlyingData + } + + /// The number of bytes in the message authentication code. + public var byteCount: Int { + self.underlyingData.count + } + + /// Invokes the given closure with a buffer pointer covering the raw bytes + /// of the code. + /// + /// - Parameters: + /// - body: A closure that takes a raw buffer pointer to the bytes of the + /// code. + public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R { + try self.underlyingData.withUnsafeBytes(body) + } + } +} + +@available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) +extension AES.CMAC { + fileprivate final class Backing { + private let key: SymmetricKey + private let context: OpaquePointer + private let outputSize: Int + + init(key: SymmetricKey, outputSize: Int) { + self.key = key + self.context = CCryptoBoringSSL_CMAC_CTX_new() + self.outputSize = outputSize + + let rc = self.key.withUnsafeBytes { keyPtr in + CCryptoBoringSSL_CMAC_Init( + self.context, + keyPtr.baseAddress, + keyPtr.count, + key.aesEVP, + nil + ) + } + precondition(rc == 1) + } + + init(copying other: Backing) { + self.key = other.key + self.context = CCryptoBoringSSL_CMAC_CTX_new() + self.outputSize = other.outputSize + let rc = CCryptoBoringSSL_CMAC_CTX_copy(self.context, other.context) + precondition(rc == 1) + + // Ensure we don't lose `other` at this time. + withExtendedLifetime(other) {} + } + + deinit { + CCryptoBoringSSL_CMAC_CTX_free(self.context) + } + + func update(_ bytes: UnsafeRawBufferPointer) { + let rc = CCryptoBoringSSL_CMAC_Update(self.context, bytes.baseAddress, bytes.count) + precondition(rc == 1) + } + + func finalize() -> AES.CMAC.MAC { + let bytes = withUnsafeTemporaryAllocation(byteCount: 16, alignment: 1) { bytes in + precondition(bytes.count >= 16) + var count = 16 + let rc = CCryptoBoringSSL_CMAC_Final(self.context, bytes.baseAddress, &count) + precondition(count == 16) + precondition(rc == 1) + + return Data(UnsafeRawBufferPointer(rebasing: bytes.prefix(self.outputSize))) + } + return AES.CMAC.MAC(underlyingData: bytes) + } + } +} + +@available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) +extension SymmetricKey { + fileprivate var aesEVP: OpaquePointer { + switch self.bitCount { + case 128: + CCryptoBoringSSL_EVP_aes_128_cbc() + case 192: + CCryptoBoringSSL_EVP_aes_192_cbc() + case 256: + CCryptoBoringSSL_EVP_aes_256_cbc() + default: + fatalError("Should be unreachable") + } + } +} diff --git a/Sources/_CryptoExtras/CMakeLists.txt b/Sources/_CryptoExtras/CMakeLists.txt index 5f9decf1f..f32a903e7 100644 --- a/Sources/_CryptoExtras/CMakeLists.txt +++ b/Sources/_CryptoExtras/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(_CryptoExtras "AES/BoringSSL/AES_CFB_boring.swift" "AES/BoringSSL/AES_CTR_boring.swift" "AES/BoringSSL/AES_GCM_SIV_boring.swift" + "AES/CMAC.swift" "ARC/ARC+API.swift" "ARC/ARC.swift" "ARC/ARCCredential.swift" diff --git a/Tests/_CryptoExtrasTests/CMACTests.swift b/Tests/_CryptoExtrasTests/CMACTests.swift new file mode 100644 index 000000000..b33f13c84 --- /dev/null +++ b/Tests/_CryptoExtrasTests/CMACTests.swift @@ -0,0 +1,197 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import Crypto +import Foundation +import XCTest +import _CryptoExtras + +final class CMACTests: XCTestCase { + // Borrowed from CryptoKit + func testVector1() throws { + let key = try Array(hexString: "a60269f095ad3c3bafae907c6f215de0") + let mac = try Array(hexString: "172084c3fe99fde4af29aa8e6e5fe1") + let msg = try Array(hexString: "cead1c5af16ca89bc0821775f8cba8c25620a03dfd27d6f1186f75f1c0bcfe4a20") + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 15) + authenticator.update(data: msg) + XCTAssert(authenticator.finalize() == mac) + } + + // rfc4493 example vectors + // https://datatracker.ietf.org/doc/html/rfc4493#page-11 + let exampleVector1 = "" + + let exampleVector2 = """ + 6bc1bee22e409f96e93d7e117393172a + """ + + let exampleVector3 = """ + 6bc1bee22e409f96e93d7e117393172a\ + ae2d8a571e03ac9c9eb76fac45af8e51\ + 30c81c46a35ce411 + """ + + let exampleVector4 = """ + 6bc1bee22e409f96e93d7e117393172a\ + ae2d8a571e03ac9c9eb76fac45af8e51\ + 30c81c46a35ce411e5fbc1191a0a52ef\ + f69f2445df4f9b17ad2b417be66c3710 + """ + + func testExampleVector1() throws { + let key = try Array(hexString: "2b7e151628aed2a6abf7158809cf4f3c") + let mac = try Array(hexString: "bb1d6929e95937287fa37d129b756746") + let msg = try Array(hexString: exampleVector1) + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 16) + authenticator.update(data: msg) + XCTAssert(authenticator.finalize() == mac) + } + + func testExampleVector2() throws { + let key = try Array(hexString: "2b7e151628aed2a6abf7158809cf4f3c") + let mac = try Array(hexString: "070a16b46b4d4144f79bdd9dd04a287c") + let msg = try Array(hexString: exampleVector2) + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 16) + authenticator.update(data: msg) + XCTAssert(authenticator.finalize() == mac) + } + + func testExampleVector2PerByte() throws { + let key = try Array(hexString: "2b7e151628aed2a6abf7158809cf4f3c") + let mac = try Array(hexString: "070a16b46b4d4144f79bdd9dd04a287c") + let msg = try Array(hexString: exampleVector2) + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 16) + for byte in msg { + authenticator.update(data: [byte]) + } + XCTAssert(authenticator.finalize() == mac) + } + + func testExampleVector3() throws { + let key = try Array(hexString: "2b7e151628aed2a6abf7158809cf4f3c") + let mac = try Array(hexString: "dfa66747de9ae63030ca32611497c827") + let msg = try Array(hexString: exampleVector3) + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 16) + authenticator.update(data: msg) + XCTAssert(authenticator.finalize() == mac) + } + + func testExampleVector3PerByte() throws { + let key = try Array(hexString: "2b7e151628aed2a6abf7158809cf4f3c") + let mac = try Array(hexString: "dfa66747de9ae63030ca32611497c827") + let msg = try Array(hexString: exampleVector3) + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 16) + for byte in msg { + authenticator.update(data: [byte]) + } + XCTAssert(authenticator.finalize() == mac) + } + + // rfc4493 example vector 4 + // https://datatracker.ietf.org/doc/html/rfc4493#page-11 + func testExampleVector4() throws { + let key = try Array(hexString: "2b7e151628aed2a6abf7158809cf4f3c") + let mac = try Array(hexString: "51f0bebf7e3b9d92fc49741779363cfe") + let msg = try Array(hexString: exampleVector4) + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 16) + authenticator.update(data: msg) + XCTAssert(authenticator.finalize() == mac) + } + + // rfc4493 example vector 4 + // https://datatracker.ietf.org/doc/html/rfc4493#page-11 + func testExampleVector4PerByte() throws { + let key = try Array(hexString: "2b7e151628aed2a6abf7158809cf4f3c") + let mac = try Array(hexString: "51f0bebf7e3b9d92fc49741779363cfe") + let msg = try Array(hexString: exampleVector4) + + var authenticator = try AES.CMAC(key: SymmetricKey(data: key), outputSize: 16) + for byte in msg { + authenticator.update(data: [byte]) + } + XCTAssert(authenticator.finalize() == mac) + } + + func testWycheproof() throws { + try wycheproofTest(jsonName: "aes_cmac_test") { (group: TestGroup) in + for test in group.tests { + precondition(test.flags.isEmpty) + + do { + var authenticator = try AES.CMAC(key: test.computedKey, outputSize: test.computedTag.count) + authenticator.update(data: test.computedMsg) + let result = authenticator.finalize() + + switch test.result { + case "valid": + XCTAssertTrue( + result == test.computedTag, + "Unexpected invalid test \(test.tcId) (\(test.comment))" + ) + case "invalid": + XCTAssertFalse( + result == test.computedTag, + "Unexpected valid test \(test.tcId) (\(test.comment))" + ) + default: + fatalError("Unexpected result type") + } + } catch { + XCTAssertTrue(test.result == "invalid", "Unexpected invalid test \(test.tcId) (\(test.comment))") + XCTAssertTrue( + test.comment == "invalid key size", + "Unexpected invalid test \(test.tcId) (\(test.comment))" + ) + } + } + } + } +} + +struct TestGroup: Codable { + var keySize: Int + var tagSize: Int + var type: String + var tests: [Test] +} + +extension TestGroup { + struct Test: Codable { + var tcId: Int + var comment: String + var key: String + var msg: String + var tag: String + var result: String + var flags: [String] + + var computedKey: SymmetricKey { + SymmetricKey(hexEncoded: self.key) + } + + var computedMsg: Data { + try! Data(hexString: self.msg) + } + + var computedTag: Data { + try! Data(hexString: self.tag) + } + } +} diff --git a/Tests/_CryptoExtrasTests/Utils/BytesUtil.swift b/Tests/_CryptoExtrasTests/Utils/BytesUtil.swift index 5cc8abc76..6fa122bfb 100644 --- a/Tests/_CryptoExtrasTests/Utils/BytesUtil.swift +++ b/Tests/_CryptoExtrasTests/Utils/BytesUtil.swift @@ -41,7 +41,11 @@ extension Array where Element == UInt8 { init(hexString: String) throws { self.init() - guard hexString.count.isMultiple(of: 2), !hexString.isEmpty else { + if hexString.count == 0 { + return + } + + if hexString.count % 2 != 0 { throw ByteHexEncodingErrors.incorrectString } diff --git a/Tests/_CryptoExtrasVectors/aes_cmac_test.json b/Tests/_CryptoExtrasVectors/aes_cmac_test.json new file mode 100644 index 000000000..53494208f --- /dev/null +++ b/Tests/_CryptoExtrasVectors/aes_cmac_test.json @@ -0,0 +1,2842 @@ +{ + "algorithm" : "AES-CMAC", + "generatorVersion" : "0.8r12", + "numberOfTests" : 308, + "header" : [ + "Test vectors of type MacTest are intended for testing the", + "generation and verification of MACs." + ], + "notes" : { + }, + "schema" : "mac_test_schema.json", + "testGroups" : [ + { + "keySize" : 128, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 1, + "comment" : "empty message", + "key" : "e34f15c7bd819930fe9d66e0c166e61c", + "msg" : "", + "tag" : "d47afca1d857a5933405b1eb7a5cb7af", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 2, + "comment" : "short message", + "key" : "e1e726677f4893890f8c027f9d8ef80d", + "msg" : "3f", + "tag" : "15f856bbed3b321952a584b3c4437a63", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 3, + "comment" : "short message", + "key" : "b151f491c4c006d1f28214aa3da9a985", + "msg" : "27d9", + "tag" : "bdbbebac982dd62b9f682618a6a604e9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 4, + "comment" : "short message", + "key" : "c36ff15f72777ee21deec07b63c1a0cd", + "msg" : "50b428", + "tag" : "be0c3ede157568af394023eb9a7cc983", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 5, + "comment" : "short message", + "key" : "32b9c5c78c3a0689a86052420fa1e8fc", + "msg" : "0b9262ec", + "tag" : "57e1506856c55dd32cd9ca821adb6c81", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 6, + "comment" : "short message", + "key" : "43151bbaef367277ebfc97509d0aa49c", + "msg" : "eaa91273e7", + "tag" : "e01adc3be6a7621824232c4285dd35b9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 7, + "comment" : "short message", + "key" : "481440298525cc261f8159159aedf62d", + "msg" : "6123c556c5cc", + "tag" : "a281e0d2d5378dfdcc1310fd9782ca56", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 8, + "comment" : "short message", + "key" : "9ca26eb88731efbf7f810d5d95e196ac", + "msg" : "7e48f06183aa40", + "tag" : "fc81761f2f7b4ce13b53d36e32677332", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 9, + "comment" : "short message", + "key" : "48f0d03e41cc55c4b58f737b5acdea32", + "msg" : "f4a133aa6d5985a0", + "tag" : "1f1cd0327c02e6d00086915937dd61d9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 10, + "comment" : "short message", + "key" : "1c958849f31996b28939ce513087d1be", + "msg" : "b0d2fee11b8e2f86b7", + "tag" : "555f462151f7dd16de698d639fb26760", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 11, + "comment" : "short message", + "key" : "39de0ebea97c09b2301a90009a423253", + "msg" : "81e5c33b4c620852f044", + "tag" : "9b004f15b7f6f366374954e64bc58f5f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 12, + "comment" : "short message", + "key" : "91656d8fc0aced60ddb1c4006d0dde53", + "msg" : "7b3e440fe566790064b2ec", + "tag" : "76672ed16c29be449e0c80785cc38e89", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 13, + "comment" : "short message", + "key" : "af7d5134720b5386158d51ea126e7cf9", + "msg" : "7cc6fcc925c20f3c83b5567c", + "tag" : "2dc5c88cf3b80ab6c0199f40be904abc", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 14, + "comment" : "short message", + "key" : "4ed56753de6f75a032ebabca3ce27971", + "msg" : "0c8c0f5619d9f8da5339281285", + "tag" : "eab4366d97e99a0850f077329ad058c0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 15, + "comment" : "short message", + "key" : "beba50c936b696c15e25046dffb23a64", + "msg" : "821ea8532fbabffb6e3d212e9b46", + "tag" : "22f33cab09c173f75d3401fe44efeead", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 16, + "comment" : "short message", + "key" : "501d81ebf912ddb87fbe3b7aac1437bc", + "msg" : "2368e3c3636b5e8e94d2081adbf798", + "tag" : "aeb784a3825168ddd61f72d0202125e6", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 17, + "comment" : "", + "key" : "e09eaa5a3f5e56d279d5e7a03373f6ea", + "msg" : "ef4eab37181f98423e53e947e7050fd0", + "tag" : "40facf0e2fb51b73a7472681b033d6dc", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 18, + "comment" : "", + "key" : "831e664c9e3f0c3094c0b27b9d908eb2", + "msg" : "26603bb76dd0a0180791c4ed4d3b058807", + "tag" : "a8144c8b24f2aa47d9c160cff4ab1716", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 19, + "comment" : "", + "key" : "549bd282ee21b4d7c3b1d02e3ee20ef7", + "msg" : "d84bf73c5eecbd38444f1a73556e2fa3253f4c54d6916545", + "tag" : "7ed458afe02f4a513f59715b664b1bbe", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 20, + "comment" : "", + "key" : "9bd3902ed0996c869b572272e76f3889", + "msg" : "a7ba19d49ee1ea02f098aa8e30c740d893a4456ccc294040484ed8a00a55f93e", + "tag" : "45082218c2d05eef32247feb1133d0a3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 21, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "96dd6e5a882cbd564c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 22, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "43802eb1931f0032afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 23, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7acfbbca7a2ea68b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 24, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "95dd6e5a882cbd564c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 25, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "40802eb1931f0032afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 26, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "79cfbbca7a2ea68b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 27, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "17dd6e5a882cbd564c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 28, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "c2802eb1931f0032afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 29, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "fbcfbbca7a2ea68b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 30, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dc6e5a882cbd564c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 31, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42812eb1931f0032afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 32, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcebbca7a2ea68b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 33, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6eda882cbd564c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 34, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802e31931f0032afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 35, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbb4a7a2ea68b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 36, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a892cbd564c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 37, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1921f0032afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 38, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7b2ea68b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 39, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a8a2cbd564c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 40, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1911f0032afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 41, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca782ea68b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 42, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbdd64c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 43, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f00b2afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 44, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea60b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 45, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564d39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 46, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032aee984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 47, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b976fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 48, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd56cc39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 49, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f00322fe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 50, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b166fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 51, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c19ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 52, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afc984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 53, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b964fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 54, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39af7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 55, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe985443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 56, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc4399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 57, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39ae7d1d5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 58, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe984443638cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 59, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc5399e74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 60, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39ae7d1e5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 61, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe984443538cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 62, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc5399d74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 63, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39ae7d9c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 64, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe98444b738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 65, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc5391f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 66, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39ae7d1c5a31ab", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 67, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe984443738cd30", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 68, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc5399f74809f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 69, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39ae7d1c5a31a8", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 70, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe984443738cd33", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 71, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc5399f74809c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 72, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39ae7d1c5a31ea", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 73, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe984443738cd71", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 74, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc5399f7480de", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 75, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbd564c39ae7d1c5a312a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 76, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f0032afe984443738cdb1", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 77, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea68b966fc5399f74801e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 78, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "96dd6e5a882cbd564d39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 79, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "43802eb1931f0032aee984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 80, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7acfbbca7a2ea68b976fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 81, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6eda882cbdd64c39ae7d1c5a31aa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 82, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802e31931f00b2afe984443738cd31", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 83, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbb4a7a2ea60b966fc5399f74809e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 84, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "97dd6e5a882cbdd64c39ae7d1c5a312a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 85, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "42802eb1931f00b2afe984443738cdb1", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 86, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7bcfbbca7a2ea60b966fc5399f74801e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 87, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "682291a577d342a9b3c65182e3a5ce55", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 88, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "bd7fd14e6ce0ffcd50167bbbc8c732ce", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 89, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "8430443585d1597469903ac6608b7f61", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 90, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 91, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 92, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 93, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 94, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 95, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 96, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "175deeda08ac3dd6ccb92efd9cdab12a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 97, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "c200ae31139f80b22f6904c4b7b84db1", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 98, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "fb4f3b4afaae260b16ef45b91ff4001e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 99, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "", + "tag" : "96dc6f5b892dbc574d38af7c1d5b30ab", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 100, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "0001020304050607", + "tag" : "43812fb0921e0133aee885453639cc30", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 101, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "7acebacb7b2fa78a976ec4389e75819f", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "keySize" : 192, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 102, + "comment" : "empty message", + "key" : "3d6bf9edae6d881eade0ff8c7076a4835b71320c1f36b631", + "msg" : "", + "tag" : "a8dd15fe2ce3495ec5b666744ec29220", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 103, + "comment" : "short message", + "key" : "915429743435c28997a33b33b6574a953d81dae0e7032e6a", + "msg" : "58", + "tag" : "e13b3f7f7f510c3a059df7a68c7e2ad5", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 104, + "comment" : "short message", + "key" : "f0c288ba26b284f9fb321b444a6517b3cdda1a799d55fdff", + "msg" : "0f7e", + "tag" : "06ef847f5f9dbf03a4f283da8c400220", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 105, + "comment" : "short message", + "key" : "6b55e4d4fd6847a80a6bfb0dcc0aa93f9fd797fc5c50292e", + "msg" : "33f530", + "tag" : "dd135053a47ca8f282c299e83b8c57c4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 106, + "comment" : "short message", + "key" : "1eb21a9e995a8e45c9e71ecbd6fe615b3e0318007c64b644", + "msg" : "3aa73c48", + "tag" : "1e93fff846934a6eea0575eecb0f0e1f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 107, + "comment" : "short message", + "key" : "710e2d5d4a9f0bc7e50796655e046a18cc5769d7764355da", + "msg" : "7e4c690a88", + "tag" : "016d4df06c68a6a788a9ea052e1b550d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 108, + "comment" : "short message", + "key" : "d8c09ea400779b63e774bdacd0cb7b5dd6f736ca23d52acf", + "msg" : "e9520280973b", + "tag" : "8030ae9f98f5d20c6089f6b1bd87c29e", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 109, + "comment" : "short message", + "key" : "8e67e9a0863b55bed408866f1cbc05357abe3f9d79f406f2", + "msg" : "4880b412287a0b", + "tag" : "bcaf50785f062a8fb8dd3c2c4cead2e1", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 110, + "comment" : "short message", + "key" : "28d8da67806410e5565bcc5a9d7ab9fb357413fa0158378c", + "msg" : "004e3f4a4e6db955", + "tag" : "c4c2c0876be9eabeb5a956da53846b08", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 111, + "comment" : "short message", + "key" : "dc968dd89fd602bb7eca6f3a8a13e4f59c08d02a514b1934", + "msg" : "41a25354efeb1bc3b8", + "tag" : "f33a62caf397f9aff71fe42941ba41d8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 112, + "comment" : "short message", + "key" : "7658951c0f620d82afd92756cc2d7983b79da3e56fdd1b78", + "msg" : "f0e82fb5c5666f4af49f", + "tag" : "4d724d05f3402967eb65ae1e32d5469e", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 113, + "comment" : "short message", + "key" : "d9574c3a221b986690931faac5258d9d3c52362b2cb9b054", + "msg" : "178ea8404ba54ee4e4522c", + "tag" : "64a0e0b6757309ab58d74f72c310e473", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 114, + "comment" : "short message", + "key" : "704409bab28085c44981f28f75dd143a4f747106f63f262e", + "msg" : "cda5709e7f115624e74ab031", + "tag" : "6ab2074334be14a95b6a241f897a43de", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 115, + "comment" : "short message", + "key" : "d8d06ef6a53bbff5c8f12d791b8f4c67e574bf440736d1cc", + "msg" : "a1171eae1979f48345dd9485a0", + "tag" : "7aa57cf98b24897cc9230e3316758e61", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 116, + "comment" : "short message", + "key" : "71129e781613f39d9ac39fbde2628b44c250c14deb5ef9e2", + "msg" : "967593cc64bcbf7f3c58d04cb82b", + "tag" : "6cc488b0a40eadbe4bcee2623239d126", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 117, + "comment" : "short message", + "key" : "850fc859e9f7b89a367611dee6698f33962d8245ca8dc331", + "msg" : "586f4f171af116519061a8e0e77940", + "tag" : "fb11a360c9776991d73d6e41d07710a2", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 118, + "comment" : "", + "key" : "f4bfa5aa4f0f4d62cf736cd2969c43d580fdb92f2753bedb", + "msg" : "0e239f239705b282ce2200fe20de1165", + "tag" : "ab20a6cf60873665b1d6999b05c7f9c6", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 119, + "comment" : "", + "key" : "cfd3f68873d81a27d2bfce876c79f6e609074dec39e34614", + "msg" : "b1973cb25aa87ef9d1a8888b0a0f5c04c6", + "tag" : "b95a016b83a0ae4194023333c8a7345a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 120, + "comment" : "", + "key" : "648a44468d67bb6744b235ee7a3fcd6ed4bdc29ec5b5fa1a", + "msg" : "c59d0d6981cca1be1d5519fc7881e6d230f39f6c12a9e827", + "tag" : "a1b96272ae7f9aef567271795f21d1d3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 121, + "comment" : "", + "key" : "9d11abc1fcb248a436598e695be12c3c2ed90a18ba09d62c", + "msg" : "aa5182cae2a8fb068c0b3fb2be3e57ae523d13dffd1a944587707c2b67447f3f", + "tag" : "8597d9a04d1c271d61d42f007b435175", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 122, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ed12390ea0a7ed15d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 123, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c81307df60859acb911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 124, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f91bde0069a6e389573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 125, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ee12390ea0a7ed15d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 126, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "cb1307df60859acb911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 127, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "fa1bde0069a6e389573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 128, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "6c12390ea0a7ed15d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 129, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "491307df60859acb911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 130, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "781bde0069a6e389573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 131, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec13390ea0a7ed15d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 132, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91207df60859acb911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 133, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81ade0069a6e389573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 134, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12398ea0a7ed15d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 135, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c913075f60859acb911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 136, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde8069a6e389573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 137, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea1a7ed15d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 138, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df61859acb911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 139, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0068a6e389573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 140, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea2a7ed15d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 141, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df62859acb911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 142, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde006ba6e389573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 143, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed95d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 144, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859a4b911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 145, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e309573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 146, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d8d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 147, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb901c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 148, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389563bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 149, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed1559d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 150, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb111c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 151, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389d73bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 152, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9f37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 153, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb913c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 154, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389571bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 155, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37b6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 156, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7ae61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 157, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf14e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 158, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37a6ecb1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 159, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7be61ae7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 160, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf04e7dde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 161, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37a6ec81fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 162, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7be619e7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 163, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf04e7ede688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 164, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37a6e4a1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 165, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7be69be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 166, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf04efcde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 167, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37a6eca1fc991", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 168, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7be61be7ca91", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 169, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf04e7cde688d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 170, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37a6eca1fc992", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 171, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7be61be7ca92", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 172, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf04e7cde688e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 173, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37a6eca1fc9d0", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 174, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7be61be7cad0", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 175, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf04e7cde68cc", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 176, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed15d9d37a6eca1fc910", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 177, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859acb911c7be61be7ca10", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 178, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e389573bf04e7cde680c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 179, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ed12390ea0a7ed15d8d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 180, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c81307df60859acb901c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 181, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f91bde0069a6e389563bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 182, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12398ea0a7ed95d9d37a6eca1fc990", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 183, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c913075f60859a4b911c7be61be7ca90", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 184, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde8069a6e309573bf04e7cde688c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 185, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ec12390ea0a7ed95d9d37a6eca1fc910", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 186, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c91307df60859a4b911c7be61be7ca10", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 187, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f81bde0069a6e309573bf04e7cde680c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 188, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "13edc6f15f5812ea262c859135e0366f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 189, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "36ecf8209f7a65346ee38419e418356f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 190, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "07e421ff96591c76a8c40fb183219773", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 191, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 192, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 193, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 194, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 195, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 196, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 197, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "6c92b98e20276d955953faee4a9f4910", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 198, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "4993875fe0051a4b119cfb669b674a10", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 199, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "789b5e80e9266309d7bb70cefc5ee80c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 200, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "", + "tag" : "ed13380fa1a6ec14d8d27b6fcb1ec891", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 201, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "0001020304050607", + "tag" : "c81206de61849bca901d7ae71ae6cb91", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 202, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "f91adf0168a7e288563af14f7ddf698d", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "keySize" : 256, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 203, + "comment" : "empty message", + "key" : "7bf9e536b66a215c22233fe2daaa743a898b9acb9f7802de70b40e3d6e43ef97", + "msg" : "", + "tag" : "736c7b56957db774c5ddf7c7a70ba8a8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 204, + "comment" : "short message", + "key" : "e754076ceab3fdaf4f9bcab7d4f0df0cbbafbc87731b8f9b7cd2166472e8eebc", + "msg" : "40", + "tag" : "9d47482c2d9252bace43a75a8335b8b8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 205, + "comment" : "short message", + "key" : "ea3b016bdd387dd64d837c71683808f335dbdc53598a4ea8c5f952473fafaf5f", + "msg" : "6601", + "tag" : "c7c44e31c466334992d6f9de3c771634", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 206, + "comment" : "short message", + "key" : "73d4709637857dafab6ad8b2b0a51b06524717fedf100296644f7cfdaae1805b", + "msg" : "f1d300", + "tag" : "b7086603a85e11fceb8cadea9bd30939", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 207, + "comment" : "short message", + "key" : "d5c81b399d4c0d1583a13da56de6d2dc45a66e7b47c24ab1192e246dc961dd77", + "msg" : "2ae63cbf", + "tag" : "ba383a3a15c9df64bba50d611113a024", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 208, + "comment" : "short message", + "key" : "2521203fa0dddf59d837b2830f87b1aa61f958155df3ca4d1df2457cb4284dc8", + "msg" : "af3a015ea1", + "tag" : "b457137c548908c629f714fe83b1ed90", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 209, + "comment" : "short message", + "key" : "665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c", + "msg" : "3f56935def3f", + "tag" : "b6d6fde93fc85de289b36b446d77b423", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 210, + "comment" : "short message", + "key" : "facd75b22221380047305bc981f570e2a1af38928ea7e2059e3af5fc6b82b493", + "msg" : "57bb86beed156f", + "tag" : "8b1ef72d0a612735b08efef981f213c2", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 211, + "comment" : "short message", + "key" : "505aa98819809ef63b9a368a1e8bc2e922da45b03ce02d9a7966b15006dba2d5", + "msg" : "2e4e7ef728fe11af", + "tag" : "f79606b83a7706a2a19e068bce818898", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 212, + "comment" : "short message", + "key" : "f942093842808ba47f64e427f7351dde6b9546e66de4e7d60aa6f328182712cf", + "msg" : "852a21d92848e627c7", + "tag" : "a5a877f22ac743b7fb9e050d2e3ddb02", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 213, + "comment" : "short message", + "key" : "64be162b39c6e5f1fed9c32d9f674d9a8cde6eaa2443214d86bd4a1fb53b81b4", + "msg" : "195a3b292f93baff0a2c", + "tag" : "6ea172e5c4d2fac075ca602de5757a62", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 214, + "comment" : "short message", + "key" : "b259a555d44b8a20c5489e2f38392ddaa6be9e35b9833b67e1b5fdf6cb3e4c6c", + "msg" : "afd73117330c6e8528a6e4", + "tag" : "68020bfc9bd73fd80d3ce581ba3b1208", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 215, + "comment" : "short message", + "key" : "2c6fc62daa77ba8c6881b3dd6989898fef646663cc7b0a3db8228a707b85f2dc", + "msg" : "0ff54d6b6759120c2e8a51e3", + "tag" : "110edd727a9bf7fa11a6358afe617d9d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 216, + "comment" : "short message", + "key" : "abab815d51df29f740e4e2079fb798e0152836e6ab57d1536ae8929e52c06eb8", + "msg" : "f0058d412a104e53d820b95a7f", + "tag" : "1fa24c6625a0f8e1fc37827ac84d3cc4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 217, + "comment" : "short message", + "key" : "3d5da1af83f7287458bff7a7651ea5d8db72259401333f6b82096996dd7eaf19", + "msg" : "aacc36972f183057919ff57b49e1", + "tag" : "868765a8fa6aa898ddec0f4123e996be", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 218, + "comment" : "short message", + "key" : "c19bdf314c6cf64381425467f42aefa17c1cc9358be16ce31b1d214859ce86aa", + "msg" : "5d066a92c300e9b6ddd63a7c13ae33", + "tag" : "b96818b7acaf879c7a7f8271375a6914", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 219, + "comment" : "", + "key" : "612e837843ceae7f61d49625faa7e7494f9253e20cb3adcea686512b043936cd", + "msg" : "cc37fae15f745a2f40e2c8b192f2b38d", + "tag" : "4b88e193000c5a4b23e95c7f2b26530b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 220, + "comment" : "", + "key" : "73216fafd0022d0d6ee27198b2272578fa8f04dd9f44467fbb6437aa45641bf7", + "msg" : "d5247b8f6c3edcbfb1d591d13ece23d2f5", + "tag" : "86911c7da51dc0823d6e93d4290d1ad4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 221, + "comment" : "", + "key" : "0427a70e257528f3ab70640bba1a5de12cf3885dd4c8e284fbbb55feb35294a5", + "msg" : "13937f8544f44270d01175a011f7670e93fa6ba7ef02336e", + "tag" : "ccb2c51bfbe2598f9109fc70ed07f0eb", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 222, + "comment" : "", + "key" : "96e1e4896fb2cd05f133a6a100bc5609a7ac3ca6d81721e922dadd69ad07a892", + "msg" : "91a17e4dfcc3166a1add26ff0e7c12056e8a654f28a6de24f4ba739ceb5b5b18", + "tag" : "925f177d85ea297ef14b203fe409f9ab", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 223, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6af0a293d8cba0101f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 224, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d709717c3a4ef8a2ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 225, + "comment" : "Flipped bit 0 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "58ee3f3b5f83e290cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 226, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "69f0a293d8cba0101f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 227, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d409717c3a4ef8a2ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 228, + "comment" : "Flipped bit 1 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "5bee3f3b5f83e290cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 229, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "ebf0a293d8cba0101f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 230, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "5609717c3a4ef8a2ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 231, + "comment" : "Flipped bit 7 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "d9ee3f3b5f83e290cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 232, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf1a293d8cba0101f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 233, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d608717c3a4ef8a2ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 234, + "comment" : "Flipped bit 8 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ef3f3b5f83e290cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 235, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a213d8cba0101f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 236, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d60971fc3a4ef8a2ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 237, + "comment" : "Flipped bit 31 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3fbb5f83e290cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 238, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d9cba0101f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 239, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3b4ef8a2ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 240, + "comment" : "Flipped bit 32 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5e83e290cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 241, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293dacba0101f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 242, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c384ef8a2ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 243, + "comment" : "Flipped bit 33 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5d83e290cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 244, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0901f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 245, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef822ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 246, + "comment" : "Flipped bit 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e210cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 247, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101e0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 248, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2eb200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 249, + "comment" : "Flipped bit 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cbe26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 250, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0109f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 251, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a26a200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 252, + "comment" : "Flipped bit 71 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e2904ae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 253, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f2089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 254, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea000b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 255, + "comment" : "Flipped bit 77 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cac26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 256, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f0088727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 257, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200a297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 258, + "comment" : "Flipped bit 80 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26cad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 259, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f0089727791b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 260, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200b297c2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 261, + "comment" : "Flipped bit 96 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26dad28bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 262, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f0089727491b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 263, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200b297f2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 264, + "comment" : "Flipped bit 97 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26dad2bbba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 265, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f008972f691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 266, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200b29fd2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 267, + "comment" : "Flipped bit 103 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26dada9bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 268, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f0089727691b7fa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 269, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200b297d2acced", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 270, + "comment" : "Flipped bit 120 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26dad29bba32c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 271, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f0089727691b7f9", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 272, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200b297d2accee", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 273, + "comment" : "Flipped bit 121 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26dad29bba32f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 274, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f0089727691b7bb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 275, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200b297d2accac", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 276, + "comment" : "Flipped bit 126 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26dad29bba36d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 277, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0101f0089727691b77b", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 278, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef8a2ea200b297d2acc6c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 279, + "comment" : "Flipped bit 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e290cae26dad29bba3ad", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 280, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6af0a293d8cba0101e0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 281, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d709717c3a4ef8a2eb200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 282, + "comment" : "Flipped bits 0 and 64 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "58ee3f3b5f83e290cbe26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 283, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a213d8cba0901f0089727691b7fb", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 284, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d60971fc3a4ef822ea200b297d2accec", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 285, + "comment" : "Flipped bits 31 and 63 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3fbb5f83e210cae26dad29bba32d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 286, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6bf0a293d8cba0901f0089727691b77b", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 287, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d609717c3a4ef822ea200b297d2acc6c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 288, + "comment" : "Flipped bits 63 and 127 in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "59ee3f3b5f83e210cae26dad29bba3ad", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 289, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "940f5d6c27345fefe0ff768d896e4804", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 290, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "29f68e83c5b1075d15dff4d682d53313", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 291, + "comment" : "all bits of tag flipped", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "a611c0c4a07c1d6f351d9252d6445cd2", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 292, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 293, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 294, + "comment" : "Tag changed to all zero", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 295, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 296, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 297, + "comment" : "tag changed to all 1", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 298, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "eb702213584b20909f8009f2f611377b", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 299, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "5689f1fcbace78226aa08ba9fdaa4c6c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 300, + "comment" : "msbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "d96ebfbbdf0362104a62ed2da93b23ad", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 301, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "", + "tag" : "6af1a392d9caa1111e0188737790b6fa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 302, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "0001020304050607", + "tag" : "d708707d3b4ff9a3eb210a287c2bcded", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 303, + "comment" : "lsbs changed in tag", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "msg" : "000102030405060708090a0b0c0d0e0f", + "tag" : "58ef3e3a5e82e391cbe36cac28baa22c", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "keySize" : 0, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 304, + "comment" : "invalid key size", + "key" : "", + "msg" : "00b9449326d39416", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "keySize" : 8, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 305, + "comment" : "invalid key size", + "key" : "0f", + "msg" : "4538b79a1397e2aa", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "keySize" : 64, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 306, + "comment" : "invalid key size", + "key" : "a88e385af7185148", + "msg" : "dc63b7ef08096e4f", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "keySize" : 160, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 307, + "comment" : "invalid key size", + "key" : "003a228008d390b645929df73a2b2bdd8298918d", + "msg" : "ad1d3c3122ab7ac6", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "keySize" : 320, + "tagSize" : 128, + "type" : "MacTest", + "tests" : [ + { + "tcId" : 308, + "comment" : "invalid key size", + "key" : "94baaac150e2645ae1ec1939c7bcefb73f6edb146fae02289b6c6326ff39bc265d612bef2727fa72", + "msg" : "e3f75a886c4a5591", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + } + ] +} From 2347f20e240cc1e98133c9794507dee7fd65f922 Mon Sep 17 00:00:00 2001 From: Si Beaumont Date: Fri, 8 Aug 2025 17:54:24 +0100 Subject: [PATCH 20/36] Use Thread.threadDictionary instead of TaskLocal for thread-local (#395) ## Motivation We were using a `@TaskLocal static var` to hold the `FiniteFieldArithmeticContext` (FFAC) on each of the curve types. The intention here was this would operate as a thread-local value, since task-locals behave like thread locals when the caller is not part of a task context. However, they still require binding, (i.e. the use of e.g. `P256.$__ffac.withValue { ... }`[^1], otherwise they just return the _default_ value, which is globally shared. We were not doing that, nor do we have a sensible place where we could. This causes crashes when using these values in a multithreaded environment since the same value will be used across threads. ## Modifications - Use an explicit thread-local API from Foundation to store and read the per-curve FFAC. - Add a test that shows each thread gets the same value on each read, but distinct from all other threads. ## Result Fixes crash when using ECToolbox-based APIs in multithreaded code. [^1]: https://developer.apple.com/documentation/swift/tasklocal#Using-task-local-values-outside-of-tasks --- .../BoringSSL/ECToolbox_boring.swift | 36 ++++++--- .../BoringSSL/ECToolboxBoringSSLTests.swift | 75 +++++++++++++++++++ 2 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift diff --git a/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift b/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift index 44d5401c2..fd369d77e 100644 --- a/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift +++ b/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift @@ -65,10 +65,16 @@ extension P256: OpenSSLSupportedNISTCurve { @inlinable static var hashToFieldByteCount: Int { 48 } - @TaskLocal @usableFromInline - // NOTE: This could be a let when Swift 6.0 is the minimum supported version. - static var __ffac = try! FiniteFieldArithmeticContext(fieldSize: P256.group.order) + static var __ffac: FiniteFieldArithmeticContext { + let key = "com.apple.swift-crypto.P256.__ffac" + if let value = Thread.current.threadDictionary[key] as? FiniteFieldArithmeticContext { + return value + } + let value = try! FiniteFieldArithmeticContext(fieldSize: P256.group.order) + Thread.current.threadDictionary[key] = value + return value + } } /// NOTE: This conformance applies to this type from the Crypto module even if it comes from the SDK. @@ -92,10 +98,16 @@ extension P384: OpenSSLSupportedNISTCurve { @inlinable static var hashToFieldByteCount: Int { 72 } - @TaskLocal @usableFromInline - // NOTE: This could be a let when Swift 6.0 is the minimum supported version. - static var __ffac = try! FiniteFieldArithmeticContext(fieldSize: P384.group.order) + static var __ffac: FiniteFieldArithmeticContext { + let key = "com.apple.swift-crypto.P384.__ffac" + if let value = Thread.current.threadDictionary[key] as? FiniteFieldArithmeticContext { + return value + } + let value = try! FiniteFieldArithmeticContext(fieldSize: P384.group.order) + Thread.current.threadDictionary[key] = value + return value + } } /// NOTE: This conformance applies to this type from the Crypto module even if it comes from the SDK. @@ -119,10 +131,16 @@ extension P521: OpenSSLSupportedNISTCurve { @inlinable static var hashToFieldByteCount: Int { 98 } - @TaskLocal @usableFromInline - // NOTE: This could be a let when Swift 6.0 is the minimum supported version. - static var __ffac = try! FiniteFieldArithmeticContext(fieldSize: P521.group.order) + static var __ffac: FiniteFieldArithmeticContext { + let key = "com.apple.swift-crypto.P521.__ffac" + if let value = Thread.current.threadDictionary[key] as? FiniteFieldArithmeticContext { + return value + } + let value = try! FiniteFieldArithmeticContext(fieldSize: P521.group.order) + Thread.current.threadDictionary[key] = value + return value + } } @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *) diff --git a/Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift b/Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift new file mode 100644 index 000000000..00dfdfff0 --- /dev/null +++ b/Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import Crypto +import Foundation +import XCTest + +@testable import _CryptoExtras + +final class ECToolboxBoringSSLTests: XCTestCase { + func testThreadLocalFFAC() async { + await testThreadLocalFFAC(P256.self) + await testThreadLocalFFAC(P384.self) + await testThreadLocalFFAC(P521.self) + } + + func testThreadLocalFFAC(_ Curve: (some OpenSSLSupportedNISTCurve & Sendable).Type) async { + let numThreads = 3 + let numReadsPerThread = 2 + + var threads: + [( + thread: Thread, + thisThreadDidReads: XCTestExpectation, + allThreadsDidReads: XCTestExpectation, + thisThreadFinished: XCTestExpectation + )] = [] + + var objectIdentifiers: [(threadID: Int, ffacID: ObjectIdentifier)] = [] + let lock = NSLock() + + for i in 1...numThreads { + let thisThreadDidReads = expectation(description: "this thread did its reads") + let allThreadsDidReads = expectation(description: "all threads did their reads") + let thisThreadFinished = expectation(description: "this thread is finished") + let thread = Thread { + for _ in 1...numReadsPerThread { + lock.lock() + objectIdentifiers.append((i, ObjectIdentifier(Curve.__ffac))) + lock.unlock() + } + thisThreadDidReads.fulfill() + XCTWaiter().wait(for: [allThreadsDidReads], timeout: .greatestFiniteMagnitude) + thisThreadFinished.fulfill() + } + thread.name = "thread-\(i)" + threads.append((thread, thisThreadDidReads, allThreadsDidReads, thisThreadFinished)) + thread.start() + } + await fulfillment(of: threads.map(\.thisThreadDidReads), timeout: 0.5) + for thread in threads { thread.allThreadsDidReads.fulfill() } + await fulfillment(of: threads.map(\.thisThreadFinished), timeout: 0.5) + + XCTAssertEqual(objectIdentifiers.count, numThreads * numReadsPerThread) + for threadID in 1...numThreads { + let partitionBoundary = objectIdentifiers.partition(by: { $0.threadID == threadID }) + let otherThreadsObjIDs = objectIdentifiers[.. Date: Mon, 11 Aug 2025 12:09:16 -0400 Subject: [PATCH 21/36] Improve vendor-boringssl.sh script to make it work better (#396) Updates for the `scripts/vendor-boringssl.h` script that make it a bit easier to use and ensure you don't accidentally get an update of BoringSSL you don't want. ### Motivation: I was working on investigating building a Swift SDK for #223 and ran into a couple of things that I saw could be improved. Not all need to be done, but at the very least I feel the boringssl revision lock should be considered. @Lukasa ### Modifications: - Add missing invocation of `$sed` in the script- `gsed` was being invoked instead, although everywhere else `$sed` was used (typo). - Support locking `BORINGSSL_REVISION` to a specific revision number through an argument to the script. This way the script can be re-run without unintentionally upgrading boringssl. - Remove the non-existent `boringssl_prefix_symbols_nasm.inc` exclude from the `CCryptoBoringSSL` target. I'm guessing it was there for an older version of boringssl, but no longer there with the current revision? ### Result: The `scripts/vendor_boringssl.sh` script behaves a bit better and can be run without upgrading the boringssl version unless explicitly desired. --- Package.swift | 1 - scripts/vendor-boringssl.sh | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index 28d7d715d..66cdbc0b4 100644 --- a/Package.swift +++ b/Package.swift @@ -98,7 +98,6 @@ let package = Package( name: "CCryptoBoringSSL", exclude: privacyManifestExclude + [ "hash.txt", - "include/boringssl_prefix_symbols_nasm.inc", "CMakeLists.txt", /* * These files are excluded to support WASI libc which doesn't provide . diff --git a/scripts/vendor-boringssl.sh b/scripts/vendor-boringssl.sh index e6ebd3bd3..50fefb4cb 100755 --- a/scripts/vendor-boringssl.sh +++ b/scripts/vendor-boringssl.sh @@ -45,6 +45,11 @@ DSTROOT=Sources/CCryptoBoringSSL TMPDIR=$(mktemp -d /tmp/.workingXXXXXX) SRCROOT="${TMPDIR}/src/boringssl.googlesource.com/boringssl" +# BoringSSL revision can be passed as the first argument to this script. +if [ "$#" -gt 0 ]; then + BORINGSSL_REVISION="$1" +fi + # This function namespaces the awkward inline functions declared in OpenSSL # and BoringSSL. function namespace_inlines { @@ -170,9 +175,14 @@ echo "CLONING boringssl" mkdir -p "$SRCROOT" git clone https://boringssl.googlesource.com/boringssl "$SRCROOT" cd "$SRCROOT" -BORINGSSL_REVISION=$(git rev-parse HEAD) +if [ "$BORINGSSL_REVISION" ]; then + echo "CHECKING OUT boringssl@${BORINGSSL_REVISION}" + git checkout "$BORINGSSL_REVISION" +else + BORINGSSL_REVISION=$(git rev-parse HEAD) + echo "CLONED boringssl@${BORINGSSL_REVISION}" +fi cd "$HERE" -echo "CLONED boringssl@${BORINGSSL_REVISION}" echo "OBTAINING submodules" ( @@ -248,7 +258,7 @@ echo "DISABLING assembly on x86 Windows" # x86 Windows builds require nasm for acceleration. SwiftPM can't do that right now, # so we disable the assembly. cd "$DSTROOT" - gsed -i "/#define OPENSSL_HEADER_BASE_H/a#if defined(_WIN32) && (defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(__x86) || defined(__i386) || defined(__i386__) || defined(_M_IX86))\n#define OPENSSL_NO_ASM\n#endif" "include/openssl/base.h" + $sed -i "/#define OPENSSL_HEADER_BASE_H/a#if defined(_WIN32) && (defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(__x86) || defined(__i386) || defined(__i386__) || defined(_M_IX86))\n#define OPENSSL_NO_ASM\n#endif" "include/openssl/base.h" ) From b7c303d97b2ad1d2b6b9c7f105a4e65d434b4881 Mon Sep 17 00:00:00 2001 From: "Jesse L. Zamora" Date: Fri, 15 Aug 2025 09:46:01 -0400 Subject: [PATCH 22/36] Use Swift SDKs to generate symbols for Linux targets and armv7 (using swift-sdk-generator) (#399) Swift SDK solution for adding armv7 symbols for swift-crypto using the [swift-sdk-generator](https://github.com/swiftlang/swift-sdk-generator). ### Motivation: As outlined in #223, the necessary symbols for armv7 are missing from swift-crypto, and we'd like to add them in some way that could be accepted by the team. It was discussed that using Swift SDKs generated from the swift-sdk-generator could be a solution that could be easily vetted, since the swift-sdk-generator is a component maintained by Apple and the swiftlang organization. ### Modifications: - Added a new `./scripts/generate-linux-sdks.sh` script to clone & build the swift-sdk-generator, and create Swift SDKs for x86_64, aarch64, and armv7. - Modified the `./scripts/vendor-boringssl.sh` script to use these installed Swift SDKs to cross-compile for Linux architectures in the script. - Ran the scripts against the exact revision of BoringSSL to avoid source updates, which adds the missing symbols for armv7. ### Result: Swift SDKs are used to generate symbols for Linux architectures instead of Docker, and missing symbols for armv7 are added as well. I have a few pros and cons for this solution: - Pros - Swift SDKs are used to cross-compile for Linux instead of Docker, which performs better than Rosetta 2 emulation. Docker does not have to be used at all for this solution. - Switching to using Swift SDKs is the more "correct" way to cross-compile for Linux targets, and much of the ecosystem for cross-compilation of Swift packages is moving to using Swift SDKs. - Cons - Lots of downloads need to happen since the swift-sdk-generator needs to download the host macOS toolchain for Swift 5.10, plus Ubuntu packages and target toolchains for each architecture (x86_64, aarch64, armv7). This results in ~15GB of artifacts in the /tmp directory for just the generator artifacts. However, this only needs to be run once before running the vendoring script. Let me know what you think @Lukasa. --- ...CryptoBoringSSL_boringssl_prefix_symbols.h | 16 ++++ ...toBoringSSL_boringssl_prefix_symbols_asm.h | 16 ++++ .../include/boringssl_prefix_symbols_nasm.inc | 32 ++++++++ scripts/generate-linux-sdks.sh | 78 +++++++++++++++++++ scripts/vendor-boringssl.sh | 10 +-- 5 files changed, 147 insertions(+), 5 deletions(-) create mode 100755 scripts/generate-linux-sdks.sh diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h index f42edc899..8b97b726b 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h @@ -640,6 +640,8 @@ #define bn_mul4x_mont_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul4x_mont_capable) #define bn_mul4x_mont_gather5 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul4x_mont_gather5) #define bn_mul4x_mont_gather5_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul4x_mont_gather5_capable) +#define bn_mul8x_mont_neon BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul8x_mont_neon) +#define bn_mul8x_mont_neon_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul8x_mont_neon_capable) #define bn_mulx_adx_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mulx_adx_capable) #define bn_mulx4x_mont BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mulx4x_mont) #define bn_mulx4x_mont_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mulx4x_mont_capable) @@ -735,6 +737,7 @@ #define boringssl_self_test_slhdsa BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, boringssl_self_test_slhdsa) #define bsaes_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bsaes_capable) #define bsaes_cbc_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bsaes_cbc_encrypt) +#define bsaes_ctr32_encrypt_blocks BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bsaes_ctr32_encrypt_blocks) #define BUF_MEM_append BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BUF_MEM_append) #define BUF_MEM_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BUF_MEM_free) #define BUF_MEM_grow BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BUF_MEM_grow) @@ -931,6 +934,7 @@ #define CRYPTO_get_thread_local BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_get_thread_local) #define CRYPTO_ghash_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_ghash_init) #define CRYPTO_has_asm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_has_asm) +#define CRYPTO_has_broken_NEON BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_has_broken_NEON) #define CRYPTO_hchacha20 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_hchacha20) #define CRYPTO_init_sysrand BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_init_sysrand) #define CRYPTO_is_ADX_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_is_ADX_capable) @@ -967,13 +971,17 @@ #define CRYPTO_MUTEX_lock_write BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_MUTEX_lock_write) #define CRYPTO_MUTEX_unlock_read BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_MUTEX_unlock_read) #define CRYPTO_MUTEX_unlock_write BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_MUTEX_unlock_write) +#define CRYPTO_needs_hwcap2_workaround BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_needs_hwcap2_workaround) #define CRYPTO_new_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_new_ex_data) #define CRYPTO_num_locks BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_num_locks) #define CRYPTO_ofb128_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_ofb128_encrypt) #define CRYPTO_once BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_once) #define CRYPTO_poly1305_finish BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_finish) +#define CRYPTO_poly1305_finish_neon BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_finish_neon) #define CRYPTO_poly1305_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_init) +#define CRYPTO_poly1305_init_neon BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_init_neon) #define CRYPTO_poly1305_update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_update) +#define CRYPTO_poly1305_update_neon BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_poly1305_update_neon) #define CRYPTO_pre_sandbox_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_pre_sandbox_init) #define CRYPTO_rdrand BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_rdrand) #define CRYPTO_rdrand_multiple8_buf BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_rdrand_multiple8_buf) @@ -2240,6 +2248,8 @@ #define OPENSSL_malloc_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, OPENSSL_malloc_init) #define OPENSSL_memdup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, OPENSSL_memdup) #define OPENSSL_no_config BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, OPENSSL_no_config) +#define openssl_poly1305_neon2_addmulmod BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, openssl_poly1305_neon2_addmulmod) +#define openssl_poly1305_neon2_blocks BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, openssl_poly1305_neon2_blocks) #define OPENSSL_posix_to_tm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, OPENSSL_posix_to_tm) #define OPENSSL_realloc BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, OPENSSL_realloc) #define OPENSSL_secure_clear_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, OPENSSL_secure_clear_free) @@ -2578,6 +2588,7 @@ #define sha1_block_data_order_avx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha1_block_data_order_avx) #define sha1_block_data_order_avx2 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha1_block_data_order_avx2) #define sha1_block_data_order_hw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha1_block_data_order_hw) +#define sha1_block_data_order_neon BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha1_block_data_order_neon) #define sha1_block_data_order_nohw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha1_block_data_order_nohw) #define sha1_block_data_order_ssse3 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha1_block_data_order_ssse3) #define SHA1_Final BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA1_Final) @@ -2594,6 +2605,7 @@ #define sha256_avx_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha256_avx_capable) #define sha256_block_data_order_avx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha256_block_data_order_avx) #define sha256_block_data_order_hw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha256_block_data_order_hw) +#define sha256_block_data_order_neon BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha256_block_data_order_neon) #define sha256_block_data_order_nohw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha256_block_data_order_nohw) #define sha256_block_data_order_ssse3 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha256_block_data_order_ssse3) #define SHA256_Final BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA256_Final) @@ -2615,6 +2627,7 @@ #define sha512_avx_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha512_avx_capable) #define sha512_block_data_order_avx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha512_block_data_order_avx) #define sha512_block_data_order_hw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha512_block_data_order_hw) +#define sha512_block_data_order_neon BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha512_block_data_order_neon) #define sha512_block_data_order_nohw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha512_block_data_order_nohw) #define SHA512_Final BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SHA512_Final) #define sha512_hw_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, sha512_hw_capable) @@ -2955,9 +2968,11 @@ #define vpaes_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_capable) #define vpaes_cbc_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_cbc_encrypt) #define vpaes_ctr32_encrypt_blocks BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_ctr32_encrypt_blocks) +#define vpaes_ctr32_encrypt_blocks_with_bsaes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_ctr32_encrypt_blocks_with_bsaes) #define vpaes_decrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_decrypt) #define vpaes_decrypt_key_to_bsaes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_decrypt_key_to_bsaes) #define vpaes_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_encrypt) +#define vpaes_encrypt_key_to_bsaes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_encrypt_key_to_bsaes) #define vpaes_set_decrypt_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_set_decrypt_key) #define vpaes_set_encrypt_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, vpaes_set_encrypt_key) #define X25519 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X25519) @@ -2974,6 +2989,7 @@ #define x25519_ge_sub BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x25519_ge_sub) #define x25519_ge_tobytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x25519_ge_tobytes) #define X25519_keypair BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X25519_keypair) +#define x25519_NEON BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x25519_NEON) #define x25519_pkey_meth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x25519_pkey_meth) #define X25519_public_from_private BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X25519_public_from_private) #define x25519_sc_reduce BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x25519_sc_reduce) diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h index 2fffdb87b..8fc7f8451 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h @@ -645,6 +645,8 @@ #define _bn_mul4x_mont_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul4x_mont_capable) #define _bn_mul4x_mont_gather5 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul4x_mont_gather5) #define _bn_mul4x_mont_gather5_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul4x_mont_gather5_capable) +#define _bn_mul8x_mont_neon BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul8x_mont_neon) +#define _bn_mul8x_mont_neon_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul8x_mont_neon_capable) #define _bn_mulx_adx_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mulx_adx_capable) #define _bn_mulx4x_mont BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mulx4x_mont) #define _bn_mulx4x_mont_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mulx4x_mont_capable) @@ -740,6 +742,7 @@ #define _boringssl_self_test_slhdsa BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, boringssl_self_test_slhdsa) #define _bsaes_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bsaes_capable) #define _bsaes_cbc_encrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bsaes_cbc_encrypt) +#define _bsaes_ctr32_encrypt_blocks BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bsaes_ctr32_encrypt_blocks) #define _BUF_MEM_append BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BUF_MEM_append) #define _BUF_MEM_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BUF_MEM_free) #define _BUF_MEM_grow BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BUF_MEM_grow) @@ -936,6 +939,7 @@ #define _CRYPTO_get_thread_local BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_get_thread_local) #define _CRYPTO_ghash_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_ghash_init) #define _CRYPTO_has_asm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_has_asm) +#define _CRYPTO_has_broken_NEON BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_has_broken_NEON) #define _CRYPTO_hchacha20 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_hchacha20) #define _CRYPTO_init_sysrand BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_init_sysrand) #define _CRYPTO_is_ADX_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_is_ADX_capable) @@ -972,13 +976,17 @@ #define _CRYPTO_MUTEX_lock_write BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_MUTEX_lock_write) #define _CRYPTO_MUTEX_unlock_read BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_MUTEX_unlock_read) #define _CRYPTO_MUTEX_unlock_write BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_MUTEX_unlock_write) +#define _CRYPTO_needs_hwcap2_workaround BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_needs_hwcap2_workaround) #define _CRYPTO_new_ex_data BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_new_ex_data) #define _CRYPTO_num_locks BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_num_locks) #define _CRYPTO_ofb128_encrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_ofb128_encrypt) #define _CRYPTO_once BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_once) #define _CRYPTO_poly1305_finish BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_poly1305_finish) +#define _CRYPTO_poly1305_finish_neon BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_poly1305_finish_neon) #define _CRYPTO_poly1305_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_poly1305_init) +#define _CRYPTO_poly1305_init_neon BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_poly1305_init_neon) #define _CRYPTO_poly1305_update BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_poly1305_update) +#define _CRYPTO_poly1305_update_neon BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_poly1305_update_neon) #define _CRYPTO_pre_sandbox_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_pre_sandbox_init) #define _CRYPTO_rdrand BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_rdrand) #define _CRYPTO_rdrand_multiple8_buf BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRYPTO_rdrand_multiple8_buf) @@ -2245,6 +2253,8 @@ #define _OPENSSL_malloc_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, OPENSSL_malloc_init) #define _OPENSSL_memdup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, OPENSSL_memdup) #define _OPENSSL_no_config BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, OPENSSL_no_config) +#define _openssl_poly1305_neon2_addmulmod BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, openssl_poly1305_neon2_addmulmod) +#define _openssl_poly1305_neon2_blocks BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, openssl_poly1305_neon2_blocks) #define _OPENSSL_posix_to_tm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, OPENSSL_posix_to_tm) #define _OPENSSL_realloc BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, OPENSSL_realloc) #define _OPENSSL_secure_clear_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, OPENSSL_secure_clear_free) @@ -2583,6 +2593,7 @@ #define _sha1_block_data_order_avx BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha1_block_data_order_avx) #define _sha1_block_data_order_avx2 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha1_block_data_order_avx2) #define _sha1_block_data_order_hw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha1_block_data_order_hw) +#define _sha1_block_data_order_neon BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha1_block_data_order_neon) #define _sha1_block_data_order_nohw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha1_block_data_order_nohw) #define _sha1_block_data_order_ssse3 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha1_block_data_order_ssse3) #define _SHA1_Final BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SHA1_Final) @@ -2599,6 +2610,7 @@ #define _sha256_avx_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha256_avx_capable) #define _sha256_block_data_order_avx BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha256_block_data_order_avx) #define _sha256_block_data_order_hw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha256_block_data_order_hw) +#define _sha256_block_data_order_neon BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha256_block_data_order_neon) #define _sha256_block_data_order_nohw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha256_block_data_order_nohw) #define _sha256_block_data_order_ssse3 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha256_block_data_order_ssse3) #define _SHA256_Final BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SHA256_Final) @@ -2620,6 +2632,7 @@ #define _sha512_avx_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha512_avx_capable) #define _sha512_block_data_order_avx BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha512_block_data_order_avx) #define _sha512_block_data_order_hw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha512_block_data_order_hw) +#define _sha512_block_data_order_neon BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha512_block_data_order_neon) #define _sha512_block_data_order_nohw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha512_block_data_order_nohw) #define _SHA512_Final BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SHA512_Final) #define _sha512_hw_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, sha512_hw_capable) @@ -2960,9 +2973,11 @@ #define _vpaes_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_capable) #define _vpaes_cbc_encrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_cbc_encrypt) #define _vpaes_ctr32_encrypt_blocks BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_ctr32_encrypt_blocks) +#define _vpaes_ctr32_encrypt_blocks_with_bsaes BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_ctr32_encrypt_blocks_with_bsaes) #define _vpaes_decrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_decrypt) #define _vpaes_decrypt_key_to_bsaes BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_decrypt_key_to_bsaes) #define _vpaes_encrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_encrypt) +#define _vpaes_encrypt_key_to_bsaes BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_encrypt_key_to_bsaes) #define _vpaes_set_decrypt_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_set_decrypt_key) #define _vpaes_set_encrypt_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, vpaes_set_encrypt_key) #define _X25519 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X25519) @@ -2979,6 +2994,7 @@ #define _x25519_ge_sub BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x25519_ge_sub) #define _x25519_ge_tobytes BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x25519_ge_tobytes) #define _X25519_keypair BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X25519_keypair) +#define _x25519_NEON BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x25519_NEON) #define _x25519_pkey_meth BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x25519_pkey_meth) #define _X25519_public_from_private BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X25519_public_from_private) #define _x25519_sc_reduce BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x25519_sc_reduce) diff --git a/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc b/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc index dcc370a72..cf0a13e6f 100644 --- a/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc +++ b/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc @@ -637,6 +637,8 @@ %xdefine _bn_mul4x_mont_capable _ %+ BORINGSSL_PREFIX %+ _bn_mul4x_mont_capable %xdefine _bn_mul4x_mont_gather5 _ %+ BORINGSSL_PREFIX %+ _bn_mul4x_mont_gather5 %xdefine _bn_mul4x_mont_gather5_capable _ %+ BORINGSSL_PREFIX %+ _bn_mul4x_mont_gather5_capable +%xdefine _bn_mul8x_mont_neon _ %+ BORINGSSL_PREFIX %+ _bn_mul8x_mont_neon +%xdefine _bn_mul8x_mont_neon_capable _ %+ BORINGSSL_PREFIX %+ _bn_mul8x_mont_neon_capable %xdefine _bn_mulx_adx_capable _ %+ BORINGSSL_PREFIX %+ _bn_mulx_adx_capable %xdefine _bn_mulx4x_mont _ %+ BORINGSSL_PREFIX %+ _bn_mulx4x_mont %xdefine _bn_mulx4x_mont_capable _ %+ BORINGSSL_PREFIX %+ _bn_mulx4x_mont_capable @@ -732,6 +734,7 @@ %xdefine _boringssl_self_test_slhdsa _ %+ BORINGSSL_PREFIX %+ _boringssl_self_test_slhdsa %xdefine _bsaes_capable _ %+ BORINGSSL_PREFIX %+ _bsaes_capable %xdefine _bsaes_cbc_encrypt _ %+ BORINGSSL_PREFIX %+ _bsaes_cbc_encrypt +%xdefine _bsaes_ctr32_encrypt_blocks _ %+ BORINGSSL_PREFIX %+ _bsaes_ctr32_encrypt_blocks %xdefine _BUF_MEM_append _ %+ BORINGSSL_PREFIX %+ _BUF_MEM_append %xdefine _BUF_MEM_free _ %+ BORINGSSL_PREFIX %+ _BUF_MEM_free %xdefine _BUF_MEM_grow _ %+ BORINGSSL_PREFIX %+ _BUF_MEM_grow @@ -928,6 +931,7 @@ %xdefine _CRYPTO_get_thread_local _ %+ BORINGSSL_PREFIX %+ _CRYPTO_get_thread_local %xdefine _CRYPTO_ghash_init _ %+ BORINGSSL_PREFIX %+ _CRYPTO_ghash_init %xdefine _CRYPTO_has_asm _ %+ BORINGSSL_PREFIX %+ _CRYPTO_has_asm +%xdefine _CRYPTO_has_broken_NEON _ %+ BORINGSSL_PREFIX %+ _CRYPTO_has_broken_NEON %xdefine _CRYPTO_hchacha20 _ %+ BORINGSSL_PREFIX %+ _CRYPTO_hchacha20 %xdefine _CRYPTO_init_sysrand _ %+ BORINGSSL_PREFIX %+ _CRYPTO_init_sysrand %xdefine _CRYPTO_is_ADX_capable _ %+ BORINGSSL_PREFIX %+ _CRYPTO_is_ADX_capable @@ -964,13 +968,17 @@ %xdefine _CRYPTO_MUTEX_lock_write _ %+ BORINGSSL_PREFIX %+ _CRYPTO_MUTEX_lock_write %xdefine _CRYPTO_MUTEX_unlock_read _ %+ BORINGSSL_PREFIX %+ _CRYPTO_MUTEX_unlock_read %xdefine _CRYPTO_MUTEX_unlock_write _ %+ BORINGSSL_PREFIX %+ _CRYPTO_MUTEX_unlock_write +%xdefine _CRYPTO_needs_hwcap2_workaround _ %+ BORINGSSL_PREFIX %+ _CRYPTO_needs_hwcap2_workaround %xdefine _CRYPTO_new_ex_data _ %+ BORINGSSL_PREFIX %+ _CRYPTO_new_ex_data %xdefine _CRYPTO_num_locks _ %+ BORINGSSL_PREFIX %+ _CRYPTO_num_locks %xdefine _CRYPTO_ofb128_encrypt _ %+ BORINGSSL_PREFIX %+ _CRYPTO_ofb128_encrypt %xdefine _CRYPTO_once _ %+ BORINGSSL_PREFIX %+ _CRYPTO_once %xdefine _CRYPTO_poly1305_finish _ %+ BORINGSSL_PREFIX %+ _CRYPTO_poly1305_finish +%xdefine _CRYPTO_poly1305_finish_neon _ %+ BORINGSSL_PREFIX %+ _CRYPTO_poly1305_finish_neon %xdefine _CRYPTO_poly1305_init _ %+ BORINGSSL_PREFIX %+ _CRYPTO_poly1305_init +%xdefine _CRYPTO_poly1305_init_neon _ %+ BORINGSSL_PREFIX %+ _CRYPTO_poly1305_init_neon %xdefine _CRYPTO_poly1305_update _ %+ BORINGSSL_PREFIX %+ _CRYPTO_poly1305_update +%xdefine _CRYPTO_poly1305_update_neon _ %+ BORINGSSL_PREFIX %+ _CRYPTO_poly1305_update_neon %xdefine _CRYPTO_pre_sandbox_init _ %+ BORINGSSL_PREFIX %+ _CRYPTO_pre_sandbox_init %xdefine _CRYPTO_rdrand _ %+ BORINGSSL_PREFIX %+ _CRYPTO_rdrand %xdefine _CRYPTO_rdrand_multiple8_buf _ %+ BORINGSSL_PREFIX %+ _CRYPTO_rdrand_multiple8_buf @@ -2237,6 +2245,8 @@ %xdefine _OPENSSL_malloc_init _ %+ BORINGSSL_PREFIX %+ _OPENSSL_malloc_init %xdefine _OPENSSL_memdup _ %+ BORINGSSL_PREFIX %+ _OPENSSL_memdup %xdefine _OPENSSL_no_config _ %+ BORINGSSL_PREFIX %+ _OPENSSL_no_config +%xdefine _openssl_poly1305_neon2_addmulmod _ %+ BORINGSSL_PREFIX %+ _openssl_poly1305_neon2_addmulmod +%xdefine _openssl_poly1305_neon2_blocks _ %+ BORINGSSL_PREFIX %+ _openssl_poly1305_neon2_blocks %xdefine _OPENSSL_posix_to_tm _ %+ BORINGSSL_PREFIX %+ _OPENSSL_posix_to_tm %xdefine _OPENSSL_realloc _ %+ BORINGSSL_PREFIX %+ _OPENSSL_realloc %xdefine _OPENSSL_secure_clear_free _ %+ BORINGSSL_PREFIX %+ _OPENSSL_secure_clear_free @@ -2575,6 +2585,7 @@ %xdefine _sha1_block_data_order_avx _ %+ BORINGSSL_PREFIX %+ _sha1_block_data_order_avx %xdefine _sha1_block_data_order_avx2 _ %+ BORINGSSL_PREFIX %+ _sha1_block_data_order_avx2 %xdefine _sha1_block_data_order_hw _ %+ BORINGSSL_PREFIX %+ _sha1_block_data_order_hw +%xdefine _sha1_block_data_order_neon _ %+ BORINGSSL_PREFIX %+ _sha1_block_data_order_neon %xdefine _sha1_block_data_order_nohw _ %+ BORINGSSL_PREFIX %+ _sha1_block_data_order_nohw %xdefine _sha1_block_data_order_ssse3 _ %+ BORINGSSL_PREFIX %+ _sha1_block_data_order_ssse3 %xdefine _SHA1_Final _ %+ BORINGSSL_PREFIX %+ _SHA1_Final @@ -2591,6 +2602,7 @@ %xdefine _sha256_avx_capable _ %+ BORINGSSL_PREFIX %+ _sha256_avx_capable %xdefine _sha256_block_data_order_avx _ %+ BORINGSSL_PREFIX %+ _sha256_block_data_order_avx %xdefine _sha256_block_data_order_hw _ %+ BORINGSSL_PREFIX %+ _sha256_block_data_order_hw +%xdefine _sha256_block_data_order_neon _ %+ BORINGSSL_PREFIX %+ _sha256_block_data_order_neon %xdefine _sha256_block_data_order_nohw _ %+ BORINGSSL_PREFIX %+ _sha256_block_data_order_nohw %xdefine _sha256_block_data_order_ssse3 _ %+ BORINGSSL_PREFIX %+ _sha256_block_data_order_ssse3 %xdefine _SHA256_Final _ %+ BORINGSSL_PREFIX %+ _SHA256_Final @@ -2612,6 +2624,7 @@ %xdefine _sha512_avx_capable _ %+ BORINGSSL_PREFIX %+ _sha512_avx_capable %xdefine _sha512_block_data_order_avx _ %+ BORINGSSL_PREFIX %+ _sha512_block_data_order_avx %xdefine _sha512_block_data_order_hw _ %+ BORINGSSL_PREFIX %+ _sha512_block_data_order_hw +%xdefine _sha512_block_data_order_neon _ %+ BORINGSSL_PREFIX %+ _sha512_block_data_order_neon %xdefine _sha512_block_data_order_nohw _ %+ BORINGSSL_PREFIX %+ _sha512_block_data_order_nohw %xdefine _SHA512_Final _ %+ BORINGSSL_PREFIX %+ _SHA512_Final %xdefine _sha512_hw_capable _ %+ BORINGSSL_PREFIX %+ _sha512_hw_capable @@ -2952,9 +2965,11 @@ %xdefine _vpaes_capable _ %+ BORINGSSL_PREFIX %+ _vpaes_capable %xdefine _vpaes_cbc_encrypt _ %+ BORINGSSL_PREFIX %+ _vpaes_cbc_encrypt %xdefine _vpaes_ctr32_encrypt_blocks _ %+ BORINGSSL_PREFIX %+ _vpaes_ctr32_encrypt_blocks +%xdefine _vpaes_ctr32_encrypt_blocks_with_bsaes _ %+ BORINGSSL_PREFIX %+ _vpaes_ctr32_encrypt_blocks_with_bsaes %xdefine _vpaes_decrypt _ %+ BORINGSSL_PREFIX %+ _vpaes_decrypt %xdefine _vpaes_decrypt_key_to_bsaes _ %+ BORINGSSL_PREFIX %+ _vpaes_decrypt_key_to_bsaes %xdefine _vpaes_encrypt _ %+ BORINGSSL_PREFIX %+ _vpaes_encrypt +%xdefine _vpaes_encrypt_key_to_bsaes _ %+ BORINGSSL_PREFIX %+ _vpaes_encrypt_key_to_bsaes %xdefine _vpaes_set_decrypt_key _ %+ BORINGSSL_PREFIX %+ _vpaes_set_decrypt_key %xdefine _vpaes_set_encrypt_key _ %+ BORINGSSL_PREFIX %+ _vpaes_set_encrypt_key %xdefine _X25519 _ %+ BORINGSSL_PREFIX %+ _X25519 @@ -2971,6 +2986,7 @@ %xdefine _x25519_ge_sub _ %+ BORINGSSL_PREFIX %+ _x25519_ge_sub %xdefine _x25519_ge_tobytes _ %+ BORINGSSL_PREFIX %+ _x25519_ge_tobytes %xdefine _X25519_keypair _ %+ BORINGSSL_PREFIX %+ _X25519_keypair +%xdefine _x25519_NEON _ %+ BORINGSSL_PREFIX %+ _x25519_NEON %xdefine _x25519_pkey_meth _ %+ BORINGSSL_PREFIX %+ _x25519_pkey_meth %xdefine _X25519_public_from_private _ %+ BORINGSSL_PREFIX %+ _X25519_public_from_private %xdefine _x25519_sc_reduce _ %+ BORINGSSL_PREFIX %+ _x25519_sc_reduce @@ -4068,6 +4084,8 @@ %xdefine bn_mul4x_mont_capable BORINGSSL_PREFIX %+ _bn_mul4x_mont_capable %xdefine bn_mul4x_mont_gather5 BORINGSSL_PREFIX %+ _bn_mul4x_mont_gather5 %xdefine bn_mul4x_mont_gather5_capable BORINGSSL_PREFIX %+ _bn_mul4x_mont_gather5_capable +%xdefine bn_mul8x_mont_neon BORINGSSL_PREFIX %+ _bn_mul8x_mont_neon +%xdefine bn_mul8x_mont_neon_capable BORINGSSL_PREFIX %+ _bn_mul8x_mont_neon_capable %xdefine bn_mulx_adx_capable BORINGSSL_PREFIX %+ _bn_mulx_adx_capable %xdefine bn_mulx4x_mont BORINGSSL_PREFIX %+ _bn_mulx4x_mont %xdefine bn_mulx4x_mont_capable BORINGSSL_PREFIX %+ _bn_mulx4x_mont_capable @@ -4163,6 +4181,7 @@ %xdefine boringssl_self_test_slhdsa BORINGSSL_PREFIX %+ _boringssl_self_test_slhdsa %xdefine bsaes_capable BORINGSSL_PREFIX %+ _bsaes_capable %xdefine bsaes_cbc_encrypt BORINGSSL_PREFIX %+ _bsaes_cbc_encrypt +%xdefine bsaes_ctr32_encrypt_blocks BORINGSSL_PREFIX %+ _bsaes_ctr32_encrypt_blocks %xdefine BUF_MEM_append BORINGSSL_PREFIX %+ _BUF_MEM_append %xdefine BUF_MEM_free BORINGSSL_PREFIX %+ _BUF_MEM_free %xdefine BUF_MEM_grow BORINGSSL_PREFIX %+ _BUF_MEM_grow @@ -4359,6 +4378,7 @@ %xdefine CRYPTO_get_thread_local BORINGSSL_PREFIX %+ _CRYPTO_get_thread_local %xdefine CRYPTO_ghash_init BORINGSSL_PREFIX %+ _CRYPTO_ghash_init %xdefine CRYPTO_has_asm BORINGSSL_PREFIX %+ _CRYPTO_has_asm +%xdefine CRYPTO_has_broken_NEON BORINGSSL_PREFIX %+ _CRYPTO_has_broken_NEON %xdefine CRYPTO_hchacha20 BORINGSSL_PREFIX %+ _CRYPTO_hchacha20 %xdefine CRYPTO_init_sysrand BORINGSSL_PREFIX %+ _CRYPTO_init_sysrand %xdefine CRYPTO_is_ADX_capable BORINGSSL_PREFIX %+ _CRYPTO_is_ADX_capable @@ -4395,13 +4415,17 @@ %xdefine CRYPTO_MUTEX_lock_write BORINGSSL_PREFIX %+ _CRYPTO_MUTEX_lock_write %xdefine CRYPTO_MUTEX_unlock_read BORINGSSL_PREFIX %+ _CRYPTO_MUTEX_unlock_read %xdefine CRYPTO_MUTEX_unlock_write BORINGSSL_PREFIX %+ _CRYPTO_MUTEX_unlock_write +%xdefine CRYPTO_needs_hwcap2_workaround BORINGSSL_PREFIX %+ _CRYPTO_needs_hwcap2_workaround %xdefine CRYPTO_new_ex_data BORINGSSL_PREFIX %+ _CRYPTO_new_ex_data %xdefine CRYPTO_num_locks BORINGSSL_PREFIX %+ _CRYPTO_num_locks %xdefine CRYPTO_ofb128_encrypt BORINGSSL_PREFIX %+ _CRYPTO_ofb128_encrypt %xdefine CRYPTO_once BORINGSSL_PREFIX %+ _CRYPTO_once %xdefine CRYPTO_poly1305_finish BORINGSSL_PREFIX %+ _CRYPTO_poly1305_finish +%xdefine CRYPTO_poly1305_finish_neon BORINGSSL_PREFIX %+ _CRYPTO_poly1305_finish_neon %xdefine CRYPTO_poly1305_init BORINGSSL_PREFIX %+ _CRYPTO_poly1305_init +%xdefine CRYPTO_poly1305_init_neon BORINGSSL_PREFIX %+ _CRYPTO_poly1305_init_neon %xdefine CRYPTO_poly1305_update BORINGSSL_PREFIX %+ _CRYPTO_poly1305_update +%xdefine CRYPTO_poly1305_update_neon BORINGSSL_PREFIX %+ _CRYPTO_poly1305_update_neon %xdefine CRYPTO_pre_sandbox_init BORINGSSL_PREFIX %+ _CRYPTO_pre_sandbox_init %xdefine CRYPTO_rdrand BORINGSSL_PREFIX %+ _CRYPTO_rdrand %xdefine CRYPTO_rdrand_multiple8_buf BORINGSSL_PREFIX %+ _CRYPTO_rdrand_multiple8_buf @@ -5668,6 +5692,8 @@ %xdefine OPENSSL_malloc_init BORINGSSL_PREFIX %+ _OPENSSL_malloc_init %xdefine OPENSSL_memdup BORINGSSL_PREFIX %+ _OPENSSL_memdup %xdefine OPENSSL_no_config BORINGSSL_PREFIX %+ _OPENSSL_no_config +%xdefine openssl_poly1305_neon2_addmulmod BORINGSSL_PREFIX %+ _openssl_poly1305_neon2_addmulmod +%xdefine openssl_poly1305_neon2_blocks BORINGSSL_PREFIX %+ _openssl_poly1305_neon2_blocks %xdefine OPENSSL_posix_to_tm BORINGSSL_PREFIX %+ _OPENSSL_posix_to_tm %xdefine OPENSSL_realloc BORINGSSL_PREFIX %+ _OPENSSL_realloc %xdefine OPENSSL_secure_clear_free BORINGSSL_PREFIX %+ _OPENSSL_secure_clear_free @@ -6006,6 +6032,7 @@ %xdefine sha1_block_data_order_avx BORINGSSL_PREFIX %+ _sha1_block_data_order_avx %xdefine sha1_block_data_order_avx2 BORINGSSL_PREFIX %+ _sha1_block_data_order_avx2 %xdefine sha1_block_data_order_hw BORINGSSL_PREFIX %+ _sha1_block_data_order_hw +%xdefine sha1_block_data_order_neon BORINGSSL_PREFIX %+ _sha1_block_data_order_neon %xdefine sha1_block_data_order_nohw BORINGSSL_PREFIX %+ _sha1_block_data_order_nohw %xdefine sha1_block_data_order_ssse3 BORINGSSL_PREFIX %+ _sha1_block_data_order_ssse3 %xdefine SHA1_Final BORINGSSL_PREFIX %+ _SHA1_Final @@ -6022,6 +6049,7 @@ %xdefine sha256_avx_capable BORINGSSL_PREFIX %+ _sha256_avx_capable %xdefine sha256_block_data_order_avx BORINGSSL_PREFIX %+ _sha256_block_data_order_avx %xdefine sha256_block_data_order_hw BORINGSSL_PREFIX %+ _sha256_block_data_order_hw +%xdefine sha256_block_data_order_neon BORINGSSL_PREFIX %+ _sha256_block_data_order_neon %xdefine sha256_block_data_order_nohw BORINGSSL_PREFIX %+ _sha256_block_data_order_nohw %xdefine sha256_block_data_order_ssse3 BORINGSSL_PREFIX %+ _sha256_block_data_order_ssse3 %xdefine SHA256_Final BORINGSSL_PREFIX %+ _SHA256_Final @@ -6043,6 +6071,7 @@ %xdefine sha512_avx_capable BORINGSSL_PREFIX %+ _sha512_avx_capable %xdefine sha512_block_data_order_avx BORINGSSL_PREFIX %+ _sha512_block_data_order_avx %xdefine sha512_block_data_order_hw BORINGSSL_PREFIX %+ _sha512_block_data_order_hw +%xdefine sha512_block_data_order_neon BORINGSSL_PREFIX %+ _sha512_block_data_order_neon %xdefine sha512_block_data_order_nohw BORINGSSL_PREFIX %+ _sha512_block_data_order_nohw %xdefine SHA512_Final BORINGSSL_PREFIX %+ _SHA512_Final %xdefine sha512_hw_capable BORINGSSL_PREFIX %+ _sha512_hw_capable @@ -6383,9 +6412,11 @@ %xdefine vpaes_capable BORINGSSL_PREFIX %+ _vpaes_capable %xdefine vpaes_cbc_encrypt BORINGSSL_PREFIX %+ _vpaes_cbc_encrypt %xdefine vpaes_ctr32_encrypt_blocks BORINGSSL_PREFIX %+ _vpaes_ctr32_encrypt_blocks +%xdefine vpaes_ctr32_encrypt_blocks_with_bsaes BORINGSSL_PREFIX %+ _vpaes_ctr32_encrypt_blocks_with_bsaes %xdefine vpaes_decrypt BORINGSSL_PREFIX %+ _vpaes_decrypt %xdefine vpaes_decrypt_key_to_bsaes BORINGSSL_PREFIX %+ _vpaes_decrypt_key_to_bsaes %xdefine vpaes_encrypt BORINGSSL_PREFIX %+ _vpaes_encrypt +%xdefine vpaes_encrypt_key_to_bsaes BORINGSSL_PREFIX %+ _vpaes_encrypt_key_to_bsaes %xdefine vpaes_set_decrypt_key BORINGSSL_PREFIX %+ _vpaes_set_decrypt_key %xdefine vpaes_set_encrypt_key BORINGSSL_PREFIX %+ _vpaes_set_encrypt_key %xdefine X25519 BORINGSSL_PREFIX %+ _X25519 @@ -6402,6 +6433,7 @@ %xdefine x25519_ge_sub BORINGSSL_PREFIX %+ _x25519_ge_sub %xdefine x25519_ge_tobytes BORINGSSL_PREFIX %+ _x25519_ge_tobytes %xdefine X25519_keypair BORINGSSL_PREFIX %+ _X25519_keypair +%xdefine x25519_NEON BORINGSSL_PREFIX %+ _x25519_NEON %xdefine x25519_pkey_meth BORINGSSL_PREFIX %+ _x25519_pkey_meth %xdefine X25519_public_from_private BORINGSSL_PREFIX %+ _X25519_public_from_private %xdefine x25519_sc_reduce BORINGSSL_PREFIX %+ _x25519_sc_reduce diff --git a/scripts/generate-linux-sdks.sh b/scripts/generate-linux-sdks.sh new file mode 100755 index 000000000..65cd7bfcb --- /dev/null +++ b/scripts/generate-linux-sdks.sh @@ -0,0 +1,78 @@ +#!/bin/bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the SwiftCrypto open source project +## +## Copyright (c) 2019-2025 Apple Inc. and the SwiftCrypto project authors +## Licensed under Apache License v2.0 +## +## See LICENSE.txt for license information +## See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +## +## SPDX-License-Identifier: Apache-2.0 +## +##===----------------------------------------------------------------------===## +# +# This script generates Swift SDKs for Linux targets using the swift-sdk-generator. +# It should be run once before running the `vendor-boringssl.sh` script, which requires +# the Linux Swift SDKs to be installed. +# +# Usage: +# 1. Run this script to generate and install the Swift SDKs. This script can be re-run to +# re-generate Swift SDKs if needed. Old SDKs will be removed before installing newly +# generated ones. +# + +set -e + +SWIFT_VERSION=5.10 +DISTRO_NAME=ubuntu +DISTRO_VERSION=jammy +DISTRO_VERSION_GENERATOR=22.04 +TMPDIR=$(mktemp -d /tmp/.workingXXXXXX) + +function generate_swift_sdk { + TARGET_ARCH=$1 + SDK_NAME="${SWIFT_VERSION}-RELEASE_${DISTRO_NAME}_${DISTRO_VERSION}_${TARGET_ARCH}" + + cd "$TMPDIR" + if [ ! -d swift-sdk-generator ]; then + echo "Cloning SDK generator..." + git clone https://github.com/swiftlang/swift-sdk-generator.git + fi + + cd swift-sdk-generator + + if [ "$TARGET_ARCH" = "armv7" ]; then + DOWNLOAD_FILE=swift-${SWIFT_VERSION}-RELEASE-${DISTRO_NAME}-${DISTRO_VERSION}-armv7-install + DOWNLOAD_PATH="${TMPDIR}/${DOWNLOAD_FILE}" + echo "Downloading armv7 runtime..." + wget -nc https://github.com/swift-embedded-linux/armhf-debian/releases/download/${SWIFT_VERSION}/${DOWNLOAD_FILE}.tar.gz && \ + echo "Extracting armv7 runtime..." && \ + mkdir "${DOWNLOAD_PATH}" && true && \ + tar -xf ${DOWNLOAD_FILE}.tar.gz -C "${DOWNLOAD_PATH}" + + echo "Creating Swift SDK for ${TARGET_ARCH}..." + swift run swift-sdk-generator make-linux-sdk \ + --swift-version ${SWIFT_VERSION}-RELEASE \ + --distribution-name ${DISTRO_NAME} \ + --distribution-version ${DISTRO_VERSION_GENERATOR} \ + --target armv7-unknown-linux-gnueabihf \ + --target-swift-package-path "${DOWNLOAD_PATH}" + else + echo "Creating Swift SDK for ${TARGET_ARCH}..." + swift run swift-sdk-generator make-linux-sdk \ + --swift-version ${SWIFT_VERSION}-RELEASE \ + --distribution-name ${DISTRO_NAME} \ + --distribution-version ${DISTRO_VERSION_GENERATOR} \ + --target "${TARGET_ARCH}-unknown-linux-gnu" + fi + + swift sdk remove "${SDK_NAME}" || true # ignore error if it doesn't exist + swift sdk install "Bundles/${SDK_NAME}.artifactbundle" +} + +echo "Generating Swift SDKs for Linux targets..." +generate_swift_sdk "x86_64" +generate_swift_sdk "aarch64" +generate_swift_sdk "armv7" diff --git a/scripts/vendor-boringssl.sh b/scripts/vendor-boringssl.sh index 50fefb4cb..b4d75ebbb 100755 --- a/scripts/vendor-boringssl.sh +++ b/scripts/vendor-boringssl.sh @@ -106,16 +106,16 @@ function mangle_symbols { ) # Now cross compile for our targets. - docker run -t -i --rm --privileged -v"$(pwd)":/src -w/src --platform linux/arm64 swift:5.10-jammy \ - swift build --product CCryptoBoringSSL - docker run -t -i --rm --privileged -v"$(pwd)":/src -w/src --platform linux/amd64 swift:5.10-jammy \ - swift build --product CCryptoBoringSSL + # NOTE: This requires running the `generate-linux-sdks.sh` script first to generate the Swift SDKs. + swift build --swift-sdk 5.10-RELEASE_ubuntu_jammy_x86_64 --product CCryptoBoringSSL + swift build --swift-sdk 5.10-RELEASE_ubuntu_jammy_aarch64 --product CCryptoBoringSSL + swift build --swift-sdk 5.10-RELEASE_ubuntu_jammy_armv7 --product CCryptoBoringSSL # Now we need to generate symbol mangles for Linux. We can do this in # one go for all of them. ( cd "${SRCROOT}" - go run "util/read_symbols.go" -obj-file-format elf -out "${TMPDIR}/symbols-linux-all.txt" "${HERE}"/.build/*-unknown-linux-gnu/debug/libCCryptoBoringSSL.a + go run "util/read_symbols.go" -obj-file-format elf -out "${TMPDIR}/symbols-linux-all.txt" "${HERE}"/.build/*-unknown-linux-*/debug/libCCryptoBoringSSL.a ) # Now we concatenate all the symbols together and uniquify it. At this stage remove anything that From d1c6b70f7c5f19fb0b8750cb8dcdf2ea6e2d8c34 Mon Sep 17 00:00:00 2001 From: aryan-25 Date: Wed, 27 Aug 2025 13:18:16 +0100 Subject: [PATCH 23/36] Avoid TSAN issue in _CryptoExtras/AES/CMAC (#402) ### Motivation: swift-crypto currently fails to compile with TSAN enabled in 5.10 and 6.0 due to a TSAN error stemming from the use of `consuming` in the `finalize()` method of `_CryptoExtras/AES/CMAC`. ### Modifications: Like #384, the `consuming finalize()` method in `_CryptoExtras/AES/CMAC` is now wrapped inside a `#if compiler(>=6.1)` condition. A non-consuming variant is used otherwise. ### Result: `swift-crypto` can successfully compile with TSAN enabled in 5.10 and 6.0. --- Sources/_CryptoExtras/AES/CMAC.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Sources/_CryptoExtras/AES/CMAC.swift b/Sources/_CryptoExtras/AES/CMAC.swift index 08b61e1cd..c96293345 100644 --- a/Sources/_CryptoExtras/AES/CMAC.swift +++ b/Sources/_CryptoExtras/AES/CMAC.swift @@ -65,6 +65,10 @@ extension AES { self.backing.update(bufferPointer) } + // This enhancement can only be present on 6.1 or later because of the + // absence of https://github.com/swiftlang/swift/pull/76186 in older + // compilers. + #if compiler(>=6.1) /// Finalizes the message authentication computation and returns the /// computed code. /// @@ -77,6 +81,16 @@ extension AES { self.cowIfNeeded() return self.backing.finalize() } + #else + /// Finalizes the message authentication computation and returns the + /// computed code. + /// + /// - Returns: The message authentication code. + public func finalize() -> AES.CMAC.MAC { + var `self` = self + return self.backing.finalize() + } + #endif /// Updates the MAC with data. /// From c46250209ea63dc1557f8b1f2ac418c85ea39e7c Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Tue, 9 Sep 2025 02:31:53 -0400 Subject: [PATCH 24/36] Move away from Foundation.Thread (#404) Motivation In preparation for adopting FoundationEssentials where available, we need to avoid using Thread as that isn't available. To that end, let's bring over NIO's ThreadSpecificVariable wrapper. Modifications Bring over NIO's ThreadSpecificVariable wrapper and supporting code. Result No need for Thread anymore. --- NOTICE.txt | 2 +- Sources/_CryptoExtras/CMakeLists.txt | 4 + .../BoringSSL/ECToolbox_boring.swift | 21 ++-- .../Util/ThreadSpecific/ThreadOps.swift | 35 ++++++ .../Util/ThreadSpecific/ThreadPosix.swift | 73 ++++++++++++ .../Util/ThreadSpecific/ThreadSpecific.swift | 111 ++++++++++++++++++ .../Util/ThreadSpecific/ThreadWindows.swift | 56 +++++++++ 7 files changed, 292 insertions(+), 10 deletions(-) create mode 100644 Sources/_CryptoExtras/Util/ThreadSpecific/ThreadOps.swift create mode 100644 Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift create mode 100644 Sources/_CryptoExtras/Util/ThreadSpecific/ThreadSpecific.swift create mode 100644 Sources/_CryptoExtras/Util/ThreadSpecific/ThreadWindows.swift diff --git a/NOTICE.txt b/NOTICE.txt index e21679747..a7756f296 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -34,7 +34,7 @@ This product contains test vectors from Google's wycheproof project. --- -This product contains a derivation of various scripts from SwiftNIO. +This product contains a derivation of various files from SwiftNIO. * LICENSE (Apache License 2.0): * https://www.apache.org/licenses/LICENSE-2.0 diff --git a/Sources/_CryptoExtras/CMakeLists.txt b/Sources/_CryptoExtras/CMakeLists.txt index f32a903e7..d4c8ea267 100644 --- a/Sources/_CryptoExtras/CMakeLists.txt +++ b/Sources/_CryptoExtras/CMakeLists.txt @@ -65,6 +65,10 @@ add_library(_CryptoExtras "Util/PEMDocument.swift" "Util/PrettyBytes.swift" "Util/SubjectPublicKeyInfo.swift" + "Util/ThreadSpecific/ThreadOps.swift" + "Util/ThreadSpecific/ThreadPosix.swift" + "Util/ThreadSpecific/ThreadSpecific.swift" + "Util/ThreadSpecific/ThreadWindows.swift" "ZKPs/DLEQ.swift" "ZKPs/Prover.swift" "ZKPs/Verifier.swift" diff --git a/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift b/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift index fd369d77e..0a08ff52f 100644 --- a/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift +++ b/Sources/_CryptoExtras/ECToolbox/BoringSSL/ECToolbox_boring.swift @@ -65,14 +65,15 @@ extension P256: OpenSSLSupportedNISTCurve { @inlinable static var hashToFieldByteCount: Int { 48 } + private static let __ffacTSV = ThreadSpecificVariable() + @usableFromInline static var __ffac: FiniteFieldArithmeticContext { - let key = "com.apple.swift-crypto.P256.__ffac" - if let value = Thread.current.threadDictionary[key] as? FiniteFieldArithmeticContext { + if let value = Self.__ffacTSV.currentValue { return value } let value = try! FiniteFieldArithmeticContext(fieldSize: P256.group.order) - Thread.current.threadDictionary[key] = value + Self.__ffacTSV.currentValue = value return value } } @@ -98,14 +99,15 @@ extension P384: OpenSSLSupportedNISTCurve { @inlinable static var hashToFieldByteCount: Int { 72 } + private static let __ffacTSV = ThreadSpecificVariable() + @usableFromInline static var __ffac: FiniteFieldArithmeticContext { - let key = "com.apple.swift-crypto.P384.__ffac" - if let value = Thread.current.threadDictionary[key] as? FiniteFieldArithmeticContext { + if let value = Self.__ffacTSV.currentValue { return value } let value = try! FiniteFieldArithmeticContext(fieldSize: P384.group.order) - Thread.current.threadDictionary[key] = value + Self.__ffacTSV.currentValue = value return value } } @@ -131,14 +133,15 @@ extension P521: OpenSSLSupportedNISTCurve { @inlinable static var hashToFieldByteCount: Int { 98 } + private static let __ffacTSV = ThreadSpecificVariable() + @usableFromInline static var __ffac: FiniteFieldArithmeticContext { - let key = "com.apple.swift-crypto.P521.__ffac" - if let value = Thread.current.threadDictionary[key] as? FiniteFieldArithmeticContext { + if let value = Self.__ffacTSV.currentValue { return value } let value = try! FiniteFieldArithmeticContext(fieldSize: P521.group.order) - Thread.current.threadDictionary[key] = value + Self.__ffacTSV.currentValue = value return value } } diff --git a/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadOps.swift b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadOps.swift new file mode 100644 index 000000000..0dc4111f4 --- /dev/null +++ b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadOps.swift @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2017-2014 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +protocol ThreadOps { + associatedtype ThreadSpecificKey + associatedtype ThreadSpecificKeyDestructor + + static func allocateThreadSpecificValue(destructor: ThreadSpecificKeyDestructor) -> ThreadSpecificKey + static func deallocateThreadSpecificValue(_ key: ThreadSpecificKey) + static func getThreadSpecificValue(_ key: ThreadSpecificKey) -> UnsafeMutableRawPointer? + static func setThreadSpecificValue(key: ThreadSpecificKey, value: UnsafeMutableRawPointer?) +} diff --git a/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift new file mode 100644 index 000000000..6b2ccdf09 --- /dev/null +++ b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if os(Linux) || os(Android) || os(FreeBSD) || canImport(Darwin) +#if canImport(Glibc) +@preconcurrency import Glibc +#elseif canImport(Bionic) +@preconcurrency import Bionic +#elseif canImport(Musl) +@preconcurrency import Musl +#elseif canImport(Android) +@preconcurrency import Android +#elseif canImport(Darwin) +import Darwin +#endif + +typealias ThreadOpsSystem = ThreadOpsPosix + +enum ThreadOpsPosix: ThreadOps { + typealias ThreadSpecificKey = pthread_key_t + #if canImport(Darwin) + typealias ThreadSpecificKeyDestructor = @convention(c) (UnsafeMutableRawPointer) -> Void + #else + typealias ThreadSpecificKeyDestructor = @convention(c) (UnsafeMutableRawPointer?) -> Void + #endif + + static func allocateThreadSpecificValue(destructor: @escaping ThreadSpecificKeyDestructor) -> ThreadSpecificKey { + var value = pthread_key_t() + let result = pthread_key_create(&value, Optional(destructor)) + precondition(result == 0, "pthread_key_create failed: \(result)") + return value + } + + static func deallocateThreadSpecificValue(_ key: ThreadSpecificKey) { + let result = pthread_key_delete(key) + precondition(result == 0, "pthread_key_delete failed: \(result)") + } + + static func getThreadSpecificValue(_ key: ThreadSpecificKey) -> UnsafeMutableRawPointer? { + pthread_getspecific(key) + } + + static func setThreadSpecificValue(key: ThreadSpecificKey, value: UnsafeMutableRawPointer?) { + let result = pthread_setspecific(key, value) + precondition(result == 0, "pthread_setspecific failed: \(result)") + } +} + +#endif diff --git a/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadSpecific.swift b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadSpecific.swift new file mode 100644 index 000000000..96eb7100b --- /dev/null +++ b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadSpecific.swift @@ -0,0 +1,111 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2019-2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// Derived from swift-nio's ThreadSpecificVariable type. + +/// A ``ThreadSpecificVariable`` is a variable that can be read and set like a normal variable except that it holds +/// different variables per thread. +/// +/// ``ThreadSpecificVariable`` is thread-safe so it can be used with multiple threads at the same time but the value +/// returned by ``currentValue`` is defined per thread. +/// +/// - Note: Though ``ThreadSpecificVariable`` is thread-safe, it is not `Sendable` unless `Value` is `Sendable`. +/// If ``ThreadSpecificVariable`` were unconditionally `Sendable`, it could be used to "smuggle" +/// non-`Sendable` state out of an actor or other isolation domain without triggering warnings. If you +/// are attempting to use ``ThreadSpecificVariable`` with non-`Sendable` data, consider using a dynamic +/// enforcement tool like `NIOLoopBoundBox` to police the access. +final class ThreadSpecificVariable { + // the actual type in there is `Box<(ThreadSpecificVariable, T)>` but we can't use that as C functions can't capture (even types) + private typealias BoxedType = Box<(AnyObject, AnyObject)> + + private class Key { + private var underlyingKey: ThreadOpsSystem.ThreadSpecificKey + + internal init(destructor: @escaping ThreadOpsSystem.ThreadSpecificKeyDestructor) { + self.underlyingKey = ThreadOpsSystem.allocateThreadSpecificValue(destructor: destructor) + } + + deinit { + ThreadOpsSystem.deallocateThreadSpecificValue(self.underlyingKey) + } + + func get() -> UnsafeMutableRawPointer? { + ThreadOpsSystem.getThreadSpecificValue(self.underlyingKey) + } + + func set(value: UnsafeMutableRawPointer?) { + ThreadOpsSystem.setThreadSpecificValue(key: self.underlyingKey, value: value) + } + } + + private let key: Key + + /// Initialize a new `ThreadSpecificVariable` without a current value (`currentValue == nil`). + init() { + self.key = Key(destructor: { + Unmanaged.fromOpaque(($0 as UnsafeMutableRawPointer?)!).release() + }) + } + + /// Initialize a new `ThreadSpecificVariable` with `value` for the calling thread. After calling this, the calling + /// thread will see `currentValue == value` but on all other threads `currentValue` will be `nil` until changed. + /// + /// - Parameters: + /// - value: The value to set for the calling thread. + convenience init(value: Value) { + self.init() + self.currentValue = value + } + + /// The value for the current thread. + @available( + *, + noasync, + message: "threads can change between suspension points and therefore the thread specific value too" + ) + var currentValue: Value? { + get { + self.get() + } + set { + self.set(newValue) + } + } + + /// Get the current value for the calling thread. + private func get() -> Value? { + guard let raw = self.key.get() else { return nil } + // parenthesize the return value to silence the cast warning + return + (Unmanaged + .fromOpaque(raw) + .takeUnretainedValue() + .value.1 as! Value) + } + + /// Set the current value for the calling threads. The `currentValue` for all other threads remains unchanged. + private func set(_ newValue: Value?) { + if let raw = self.key.get() { + Unmanaged.fromOpaque(raw).release() + } + self.key.set(value: newValue.map { Unmanaged.passRetained(Box((self, $0))).toOpaque() }) + } +} + +extension ThreadSpecificVariable: @unchecked Sendable where Value: Sendable {} + +final class Box { + let value: T + init(_ value: T) { self.value = value } +} diff --git a/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadWindows.swift b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadWindows.swift new file mode 100644 index 000000000..6cbacedd7 --- /dev/null +++ b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadWindows.swift @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if os(Windows) + +import WinSDK + +typealias ThreadOpsSystem = ThreadOpsWindows + +enum ThreadOpsWindows: ThreadOps { + typealias ThreadSpecificKey = DWORD + typealias ThreadSpecificKeyDestructor = @convention(c) (UnsafeMutableRawPointer?) -> Void + + static func allocateThreadSpecificValue(destructor: @escaping ThreadSpecificKeyDestructor) -> ThreadSpecificKey { + FlsAlloc(destructor) + } + + static func deallocateThreadSpecificValue(_ key: ThreadSpecificKey) { + let dwResult: Bool = FlsFree(key) + precondition(dwResult, "FlsFree: \(GetLastError())") + } + + static func getThreadSpecificValue(_ key: ThreadSpecificKey) -> UnsafeMutableRawPointer? { + FlsGetValue(key) + } + + static func setThreadSpecificValue(key: ThreadSpecificKey, value: UnsafeMutableRawPointer?) { + FlsSetValue(key, value) + } +} + +#endif From 9552067c746583b76b44e01b43c034d6bfc40891 Mon Sep 17 00:00:00 2001 From: Tim Condon <0xTim@users.noreply.github.com> Date: Tue, 9 Sep 2025 07:53:45 +0100 Subject: [PATCH 25/36] Fix script path in PR template (#408) Fix PR template to point to correct script --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b62b40d3f..6bfe680f0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,7 +9,7 @@ _[One line description of your change]_ - [ ] I've updated the documentation if necessary #### If you've made changes to `gyb` files -- [ ] I've run `.script/generate_boilerplate_files_with_gyb` and included updated generated files in a commit of this pull request +- [ ] I've run `./scripts/generate_boilerplate_files_with_gyb.sh` and included updated generated files in a commit of this pull request ### Motivation: @@ -21,4 +21,4 @@ _[Describe the modifications you've done.]_ ### Result: -_[After your change, what will change.]_ \ No newline at end of file +_[After your change, what will change.]_ From 141f5b4e1703cadf56fe8e53b8f964784c91aa84 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Tue, 9 Sep 2025 04:04:31 -0400 Subject: [PATCH 26/36] Make the tests Swift 6 ready. (#409) This little box type allows us to easily audit the correctness of the locking. --- .../BoringSSL/ECToolboxBoringSSLTests.swift | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift b/Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift index 00dfdfff0..0e9a9d5a2 100644 --- a/Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift +++ b/Tests/_CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift @@ -36,8 +36,7 @@ final class ECToolboxBoringSSLTests: XCTestCase { thisThreadFinished: XCTestExpectation )] = [] - var objectIdentifiers: [(threadID: Int, ffacID: ObjectIdentifier)] = [] - let lock = NSLock() + let objectIdentifiers: LockedBox<[(threadID: Int, ffacID: ObjectIdentifier)]> = .init(initialValue: []) for i in 1...numThreads { let thisThreadDidReads = expectation(description: "this thread did its reads") @@ -45,9 +44,9 @@ final class ECToolboxBoringSSLTests: XCTestCase { let thisThreadFinished = expectation(description: "this thread is finished") let thread = Thread { for _ in 1...numReadsPerThread { - lock.lock() - objectIdentifiers.append((i, ObjectIdentifier(Curve.__ffac))) - lock.unlock() + objectIdentifiers.withLockedValue { + $0.append((i, ObjectIdentifier(Curve.__ffac))) + } } thisThreadDidReads.fulfill() XCTWaiter().wait(for: [allThreadsDidReads], timeout: .greatestFiniteMagnitude) @@ -61,15 +60,39 @@ final class ECToolboxBoringSSLTests: XCTestCase { for thread in threads { thread.allThreadsDidReads.fulfill() } await fulfillment(of: threads.map(\.thisThreadFinished), timeout: 0.5) - XCTAssertEqual(objectIdentifiers.count, numThreads * numReadsPerThread) - for threadID in 1...numThreads { - let partitionBoundary = objectIdentifiers.partition(by: { $0.threadID == threadID }) - let otherThreadsObjIDs = objectIdentifiers[..: @unchecked Sendable { + private let lock: NSLock + private var value: Value + + init(initialValue: Value) { + self.value = initialValue + self.lock = NSLock() + } + + func withLockedValue(_ body: (inout Value) throws -> ReturnType) rethrows -> ReturnType { + self.lock.lock() + defer { + self.lock.unlock() } + return try body(&self.value) } } From c661debfc281ed66881668a3e3648956c6a14cec Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Mon, 15 Sep 2025 09:21:20 -0500 Subject: [PATCH 27/36] Update BoringSSL to 0226f30467f540a3f62ef48d453f93927da199b6 (#406) Fix multiple issues in the BoringSSL vendoring script and update BoringSSL to 0226f30467f540a3f62ef48d453f93927da199b6 ### Checklist - [x] I've run tests to see all new and existing tests pass - [x] I've followed the code style of the rest of the project - [x] I've read the [Contribution Guidelines](CONTRIBUTING.md) - [x] I've updated the documentation if necessary ### Motivation: The `vendor-boringssl.sh` script is currently broken in a number of ways, both in general and relative to the latest BoringSSL version: - `--enable-test-discovery` is still in use - The Linux Swift SDKs being generated are out of date (5.10-jammy) - The script does not prefix exported C++ symbols - Invoking the script without a `BORINGSSL_REVISION` results in an unconditional error - The `PATTERNS` list is out of date for the latest BoringSSL - The latest BoringSSL contains a bug which fails to apply `extern "C"` to two exported symbols, allowing for collisions. In addition, the latest BoringSSL has made `BN_MONT_CTX` opaque, necessitating that it be referenced with `OpaquePointer` rather than `UnsafePointer<>`. ### Modifications: The following changes are included: - `--enable-test-discovery` has been removed - `vendor-boringssl.sh` and `generate-linux-sdks.sh` have been updated to use Swift 6.1.2 SDKs built for Ubuntu Noble - The `mangle_cpp_structures` function from `swift-nio-ssl`'s version of `vendor-boringssl.sh` has been copied over (thanks @Lukasa!) - `BORINGSSL_REVISION` is now allowed to be an empty string - The `PATTERNS` array has been updated - A patch has been added which applies `extern "C"` to the functions which should have it - `s/UnsafePointer/OpaquePointer/g` - Updated `CMakeLists.txt` per `update-cmake-lists.sh` - Update BoringSSL to `0226f30467f540a3f62ef48d453f93927da199b6` ### Result: Vendoring the latest BoringSSL will work again. The latest BoringSSL is vendored. --- Package.swift | 2 +- Sources/CCryptoBoringSSL/CMakeLists.txt | 1 - .../CCryptoBoringSSL/crypto/asn1/a_bitstr.cc | 123 ++- .../CCryptoBoringSSL/crypto/asn1/a_bool.cc | 11 +- .../CCryptoBoringSSL/crypto/asn1/a_gentm.cc | 17 + Sources/CCryptoBoringSSL/crypto/asn1/a_int.cc | 96 +- .../CCryptoBoringSSL/crypto/asn1/a_object.cc | 98 +- .../CCryptoBoringSSL/crypto/asn1/a_strnid.cc | 6 +- .../CCryptoBoringSSL/crypto/asn1/a_time.cc | 16 + .../CCryptoBoringSSL/crypto/asn1/a_type.cc | 218 ++++ .../CCryptoBoringSSL/crypto/asn1/a_utctm.cc | 16 + .../CCryptoBoringSSL/crypto/asn1/asn1_lib.cc | 79 +- .../CCryptoBoringSSL/crypto/asn1/internal.h | 242 ++++- .../CCryptoBoringSSL/crypto/asn1/tasn_dec.cc | 469 ++++----- .../CCryptoBoringSSL/crypto/asn1/tasn_typ.cc | 3 + .../CCryptoBoringSSL/crypto/asn1/tasn_utl.cc | 24 +- .../CCryptoBoringSSL/crypto/blake2/blake2.cc | 4 +- .../crypto/bytestring/internal.h | 60 +- .../crypto/cipher/e_aesctrhmac.cc | 2 +- .../CCryptoBoringSSL/crypto/cipher/e_tls.cc | 56 +- .../crypto/cipher/get_cipher.cc | 20 +- .../CCryptoBoringSSL/crypto/cipher/internal.h | 3 +- Sources/CCryptoBoringSSL/crypto/conf/conf.cc | 2 + Sources/CCryptoBoringSSL/crypto/crypto.cc | 2 + .../crypto/curve25519/curve25519.cc | 2 +- .../crypto/curve25519/spake25519.cc | 11 +- Sources/CCryptoBoringSSL/crypto/dh/dh_asn1.cc | 26 +- Sources/CCryptoBoringSSL/crypto/dh/params.cc | 18 +- .../crypto/digest/digest_extra.cc | 77 +- Sources/CCryptoBoringSSL/crypto/dsa/dsa.cc | 2 +- .../CCryptoBoringSSL/crypto/dsa/dsa_asn1.cc | 104 +- Sources/CCryptoBoringSSL/crypto/ec/ec_asn1.cc | 224 ++-- Sources/CCryptoBoringSSL/crypto/ec/internal.h | 27 + .../crypto/ecdsa/ecdsa_asn1.cc | 25 +- Sources/CCryptoBoringSSL/crypto/evp/evp.cc | 144 ++- .../CCryptoBoringSSL/crypto/evp/evp_asn1.cc | 400 ++++--- .../CCryptoBoringSSL/crypto/evp/evp_ctx.cc | 31 +- .../CCryptoBoringSSL/crypto/evp/internal.h | 127 ++- Sources/CCryptoBoringSSL/crypto/evp/p_dh.cc | 2 +- .../CCryptoBoringSSL/crypto/evp/p_dh_asn1.cc | 10 +- .../CCryptoBoringSSL/crypto/evp/p_dsa_asn1.cc | 64 +- Sources/CCryptoBoringSSL/crypto/evp/p_ec.cc | 17 +- .../CCryptoBoringSSL/crypto/evp/p_ec_asn1.cc | 121 ++- .../CCryptoBoringSSL/crypto/evp/p_ed25519.cc | 7 +- .../crypto/evp/p_ed25519_asn1.cc | 36 +- Sources/CCryptoBoringSSL/crypto/evp/p_hkdf.cc | 2 +- Sources/CCryptoBoringSSL/crypto/evp/p_rsa.cc | 315 +++--- .../CCryptoBoringSSL/crypto/evp/p_rsa_asn1.cc | 212 +++- .../CCryptoBoringSSL/crypto/evp/p_x25519.cc | 8 +- .../crypto/evp/p_x25519_asn1.cc | 34 +- Sources/CCryptoBoringSSL/crypto/evp/print.cc | 77 +- .../CCryptoBoringSSL/crypto/fipsmodule/bcm.cc | 7 +- .../crypto/fipsmodule/bcm_interface.h | 134 +++ .../fipsmodule/bn/exponentiation.cc.inc | 22 +- .../crypto/fipsmodule/bn/generic.cc.inc | 44 +- .../crypto/fipsmodule/bn/internal.h | 64 +- .../crypto/fipsmodule/bn/montgomery.cc.inc | 25 +- .../crypto/fipsmodule/bn/prime.cc.inc | 6 +- .../crypto/fipsmodule/dh/dh.cc.inc | 4 +- .../crypto/fipsmodule/digest/digest.cc.inc | 43 +- .../crypto/fipsmodule/digest/digests.cc.inc | 4 + .../crypto/fipsmodule/ec/ec.cc.inc | 36 +- .../crypto/fipsmodule/ec/oct.cc.inc | 4 +- .../crypto/fipsmodule/ec/p256-nistz.cc.inc | 6 +- .../crypto/fipsmodule/ec/p256.cc.inc | 256 +---- .../crypto/fipsmodule/ec/simple_mul.cc.inc | 17 +- .../crypto/fipsmodule/ec/wnaf.cc.inc | 6 +- .../crypto/fipsmodule/entropy/internal.h | 38 + .../crypto/fipsmodule/entropy/jitter.cc.inc | 463 ++++++++ .../crypto/fipsmodule/entropy/sha512.cc.inc | 324 ++++++ .../crypto/fipsmodule/mldsa/mldsa.cc.inc | 574 ++++++++-- .../crypto/fipsmodule/rand/ctrdrbg.cc.inc | 271 ++++- .../crypto/fipsmodule/rand/internal.h | 17 +- .../crypto/fipsmodule/rand/rand.cc.inc | 44 +- .../crypto/fipsmodule/rsa/padding.cc.inc | 26 +- .../crypto/fipsmodule/rsa/rsa.cc.inc | 12 +- .../crypto/fipsmodule/rsa/rsa_impl.cc.inc | 34 +- .../crypto/fipsmodule/self_check/fips.cc.inc | 4 +- .../fipsmodule/self_check/self_check.cc.inc | 49 +- .../fipsmodule/service_indicator/internal.h | 7 + .../service_indicator.cc.inc | 3 +- .../crypto/fipsmodule/sha/sha512.cc.inc | 30 +- .../crypto/fipsmodule/slhdsa/thash.cc.inc | 2 +- Sources/CCryptoBoringSSL/crypto/hpke/hpke.cc | 121 ++- Sources/CCryptoBoringSSL/crypto/hrss/hrss.cc | 6 +- Sources/CCryptoBoringSSL/crypto/internal.h | 77 +- .../CCryptoBoringSSL/crypto/kyber/internal.h | 111 +- .../CCryptoBoringSSL/crypto/kyber/kyber.cc | 3 - .../CCryptoBoringSSL/crypto/mldsa/mldsa.cc | 104 ++ Sources/CCryptoBoringSSL/crypto/obj/obj.cc | 17 +- Sources/CCryptoBoringSSL/crypto/obj/obj_dat.h | 5 +- .../CCryptoBoringSSL/crypto/obj/obj_xref.cc | 16 +- .../CCryptoBoringSSL/crypto/pem/pem_all.cc | 23 +- .../CCryptoBoringSSL/crypto/pem/pem_info.cc | 4 +- .../CCryptoBoringSSL/crypto/pem/pem_lib.cc | 4 +- .../CCryptoBoringSSL/crypto/pkcs8/p5_pbev2.cc | 1 + .../CCryptoBoringSSL/crypto/pkcs8/pkcs8.cc | 16 +- .../crypto/pkcs8/pkcs8_x509.cc | 1 + .../CCryptoBoringSSL/crypto/rand/passive.cc | 2 +- .../CCryptoBoringSSL/crypto/rsa/internal.h | 25 + .../CCryptoBoringSSL/crypto/rsa/rsa_asn1.cc | 204 +++- .../CCryptoBoringSSL/crypto/rsa/rsa_extra.cc | 11 + Sources/CCryptoBoringSSL/crypto/sha/sha256.cc | 2 +- Sources/CCryptoBoringSSL/crypto/sha/sha512.cc | 2 +- .../crypto/spake2plus/internal.h | 2 +- .../crypto/spake2plus/spake2plus.cc | 2 +- .../crypto/trust_token/pmbtoken.cc | 11 +- .../crypto/trust_token/trust_token.cc | 11 +- .../crypto/trust_token/voprf.cc | 2 +- .../CCryptoBoringSSL/crypto/x509/a_sign.cc | 91 +- .../CCryptoBoringSSL/crypto/x509/a_verify.cc | 52 +- .../CCryptoBoringSSL/crypto/x509/algorithm.cc | 14 +- .../CCryptoBoringSSL/crypto/x509/asn1_gen.cc | 6 +- .../CCryptoBoringSSL/crypto/x509/by_file.cc | 12 +- .../CCryptoBoringSSL/crypto/x509/internal.h | 79 +- .../CCryptoBoringSSL/crypto/x509/rsa_pss.cc | 350 ++---- Sources/CCryptoBoringSSL/crypto/x509/t_req.cc | 2 +- .../CCryptoBoringSSL/crypto/x509/t_x509.cc | 17 +- .../CCryptoBoringSSL/crypto/x509/v3_conf.cc | 2 +- .../CCryptoBoringSSL/crypto/x509/v3_purp.cc | 12 +- .../CCryptoBoringSSL/crypto/x509/v3_skey.cc | 11 +- .../CCryptoBoringSSL/crypto/x509/x509_cmp.cc | 37 +- .../CCryptoBoringSSL/crypto/x509/x509_ext.cc | 57 +- .../CCryptoBoringSSL/crypto/x509/x509_lu.cc | 4 +- .../CCryptoBoringSSL/crypto/x509/x509_set.cc | 111 +- .../CCryptoBoringSSL/crypto/x509/x509_trs.cc | 6 +- .../CCryptoBoringSSL/crypto/x509/x509cset.cc | 15 +- .../CCryptoBoringSSL/crypto/x509/x509rset.cc | 9 +- .../CCryptoBoringSSL/crypto/x509/x_algor.cc | 132 ++- Sources/CCryptoBoringSSL/crypto/x509/x_all.cc | 63 +- .../CCryptoBoringSSL/crypto/x509/x_name.cc | 72 +- .../CCryptoBoringSSL/crypto/x509/x_pubkey.cc | 189 ++-- Sources/CCryptoBoringSSL/crypto/x509/x_val.cc | 28 - .../CCryptoBoringSSL/crypto/x509/x_x509.cc | 449 ++++---- .../gen/bcm/armv8-mont-apple.S | 10 +- .../gen/bcm/armv8-mont-linux.S | 14 +- .../CCryptoBoringSSL/gen/bcm/armv8-mont-win.S | 10 +- .../CCryptoBoringSSL/gen/bcm/x86-mont-apple.S | 8 +- .../CCryptoBoringSSL/gen/bcm/x86-mont-linux.S | 12 +- .../CCryptoBoringSSL/gen/crypto/err_data.cc | 992 +++++++++--------- Sources/CCryptoBoringSSL/hash.txt | 2 +- .../include/CCryptoBoringSSL_asn1.h | 12 - .../include/CCryptoBoringSSL_asn1t.h | 4 +- .../include/CCryptoBoringSSL_base.h | 1 + .../include/CCryptoBoringSSL_bcm_public.h | 7 +- .../include/CCryptoBoringSSL_blake2.h | 7 +- .../include/CCryptoBoringSSL_bn.h | 10 - ...CryptoBoringSSL_boringssl_prefix_symbols.h | 112 +- ...toBoringSSL_boringssl_prefix_symbols_asm.h | 110 +- .../include/CCryptoBoringSSL_conf.h | 3 + .../include/CCryptoBoringSSL_crypto.h | 8 +- .../include/CCryptoBoringSSL_ctrdrbg.h | 48 +- .../include/CCryptoBoringSSL_dh.h | 20 +- .../include/CCryptoBoringSSL_digest.h | 21 +- .../include/CCryptoBoringSSL_dsa.h | 2 +- .../include/CCryptoBoringSSL_ec.h | 46 +- .../include/CCryptoBoringSSL_ec_key.h | 4 +- .../include/CCryptoBoringSSL_err.h | 7 + .../include/CCryptoBoringSSL_evp.h | 341 ++++-- .../include/CCryptoBoringSSL_evp_errors.h | 2 +- .../include/CCryptoBoringSSL_hpke.h | 8 +- .../include/CCryptoBoringSSL_mldsa.h | 140 +++ .../include/CCryptoBoringSSL_nid.h | 5 +- .../include/CCryptoBoringSSL_rsa.h | 57 +- .../include/CCryptoBoringSSL_sha.h | 163 +-- .../include/CCryptoBoringSSL_sha2.h | 184 ++++ .../include/CCryptoBoringSSL_x509.h | 156 +-- .../include/boringssl_prefix_symbols_nasm.inc | 220 +++- .../experimental/CCryptoBoringSSL_kyber.h | 146 --- .../fiat/bedrock_polyfill_platform.c.inc | 66 ++ .../fiat/bedrock_unverified_bareminimum.c.inc | 47 + .../fiat/bedrock_unverified_platform.c.inc | 125 +++ .../third_party/fiat/p256_64.h | 77 +- .../third_party/fiat/p256_64_msvc.h | 75 +- .../third_party/fiat/p256_field.c.inc | 26 + .../third_party/fiat/p256_field_32.br.c.inc | 71 ++ .../third_party/fiat/p256_field_64.br.c.inc | 84 ++ .../third_party/fiat/p256_point.br.c.inc | 112 ++ .../Util/FiniteFieldArithmeticContext.swift | 4 +- scripts/generate-linux-sdks.sh | 6 +- scripts/patch-3-missing-extern-c.patch | 25 + scripts/vendor-boringssl.sh | 58 +- 182 files changed, 8120 insertions(+), 4420 deletions(-) create mode 100644 Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/internal.h create mode 100644 Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/jitter.cc.inc create mode 100644 Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/sha512.cc.inc delete mode 100644 Sources/CCryptoBoringSSL/crypto/x509/x_val.cc create mode 100644 Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha2.h delete mode 100644 Sources/CCryptoBoringSSL/include/experimental/CCryptoBoringSSL_kyber.h create mode 100644 Sources/CCryptoBoringSSL/third_party/fiat/bedrock_polyfill_platform.c.inc create mode 100644 Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_bareminimum.c.inc create mode 100644 Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_platform.c.inc create mode 100644 Sources/CCryptoBoringSSL/third_party/fiat/p256_field.c.inc create mode 100644 Sources/CCryptoBoringSSL/third_party/fiat/p256_field_32.br.c.inc create mode 100644 Sources/CCryptoBoringSSL/third_party/fiat/p256_field_64.br.c.inc create mode 100644 Sources/CCryptoBoringSSL/third_party/fiat/p256_point.br.c.inc create mode 100644 scripts/patch-3-missing-extern-c.patch diff --git a/Package.swift b/Package.swift index 66cdbc0b4..59c17ab1d 100644 --- a/Package.swift +++ b/Package.swift @@ -20,7 +20,7 @@ // Sources/CCryptoBoringSSL directory. The source repository is at // https://boringssl.googlesource.com/boringssl. // -// BoringSSL Commit: 035e720641f385e82c72b7b0a9e1d89e58cb5ed5 +// BoringSSL Commit: 0226f30467f540a3f62ef48d453f93927da199b6 import PackageDescription diff --git a/Sources/CCryptoBoringSSL/CMakeLists.txt b/Sources/CCryptoBoringSSL/CMakeLists.txt index 9da329bd4..7e58e0d86 100644 --- a/Sources/CCryptoBoringSSL/CMakeLists.txt +++ b/Sources/CCryptoBoringSSL/CMakeLists.txt @@ -255,7 +255,6 @@ add_library(CCryptoBoringSSL STATIC "crypto/x509/x_req.cc" "crypto/x509/x_sig.cc" "crypto/x509/x_spki.cc" - "crypto/x509/x_val.cc" "crypto/x509/x_x509.cc" "crypto/x509/x_x509a.cc" "crypto/xwing/xwing.cc" diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_bitstr.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_bitstr.cc index dcfc1fe09..4f26f2250 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_bitstr.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_bitstr.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "../internal.h" #include "internal.h" @@ -110,76 +111,96 @@ int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in, CBB_flush(out); } -ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, - const unsigned char **pp, long len) { - ASN1_BIT_STRING *ret = NULL; - const unsigned char *p; - unsigned char *s; - int padding; - uint8_t padding_mask; - - if (len < 1) { +static int asn1_parse_bit_string_contents(bssl::Span in, + ASN1_BIT_STRING *out) { + CBS cbs = in; + uint8_t padding; + if (!CBS_get_u8(&cbs, &padding)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); - goto err; + return 0; } - if (len > INT_MAX) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); - goto err; + if (padding > 7) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + return 0; } - if ((a == NULL) || ((*a) == NULL)) { - if ((ret = ASN1_BIT_STRING_new()) == NULL) { - return NULL; + // Unused bits in a BIT STRING must be zero. + uint8_t padding_mask = (1 << padding) - 1; + if (padding != 0) { + CBS copy = cbs; + uint8_t last; + if (!CBS_get_last_u8(©, &last) || (last & padding_mask) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); + return 0; } - } else { - ret = (*a); } - p = *pp; - padding = *(p++); - len--; - if (padding > 7) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); - goto err; + if (!ASN1_STRING_set(out, CBS_data(&cbs), CBS_len(&cbs))) { + return 0; } - // Unused bits in a BIT STRING must be zero. - padding_mask = (1 << padding) - 1; - if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); - goto err; - } + out->type = V_ASN1_BIT_STRING; + // |ASN1_STRING_FLAG_BITS_LEFT| and the bottom 3 bits encode |padding|. + out->flags &= ~0x07; + out->flags |= ASN1_STRING_FLAG_BITS_LEFT | padding; + return 1; +} - // We do this to preserve the settings. If we modify the settings, via - // the _set_bit function, we will recalculate on output - ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); // clear - ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); // set +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, + const unsigned char **pp, long len) { + if (len < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); + return nullptr; + } - if (len > 0) { - s = reinterpret_cast(OPENSSL_memdup(p, len)); - if (s == NULL) { - goto err; + ASN1_BIT_STRING *ret = nullptr; + if (a == nullptr || *a == nullptr) { + if ((ret = ASN1_BIT_STRING_new()) == nullptr) { + return nullptr; } - p += len; } else { - s = NULL; + ret = *a; } - ret->length = (int)len; - OPENSSL_free(ret->data); - ret->data = s; - ret->type = V_ASN1_BIT_STRING; - if (a != NULL) { - (*a) = ret; + if (!asn1_parse_bit_string_contents(bssl::Span(*pp, len), ret)) { + if (ret != nullptr && (a == nullptr || *a != ret)) { + ASN1_BIT_STRING_free(ret); + } + return nullptr; } - *pp = p; + + if (a != nullptr) { + *a = ret; + } + *pp += len; return ret; -err: - if ((ret != NULL) && ((a == NULL) || (*a != ret))) { - ASN1_BIT_STRING_free(ret); +} + +int asn1_parse_bit_string(CBS *cbs, ASN1_BIT_STRING *out, CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_BITSTRING : tag; + CBS child; + if (!CBS_get_asn1(cbs, &child, tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + return asn1_parse_bit_string_contents(child, out); +} + +int asn1_parse_bit_string_with_bad_length(CBS *cbs, ASN1_BIT_STRING *out) { + CBS child; + CBS_ASN1_TAG tag; + size_t header_len; + int indefinite; + if (!CBS_get_any_ber_asn1_element(cbs, &child, &tag, &header_len, + /*out_ber_found=*/nullptr, + &indefinite) || + tag != CBS_ASN1_BITSTRING || indefinite || // + !CBS_skip(&child, header_len)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; } - return NULL; + return asn1_parse_bit_string_contents(child, out); } // These next 2 functions from Goetz Babin-Ebell diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_bool.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_bool.cc index 5a52ac477..ea18ba964 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_bool.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_bool.cc @@ -21,13 +21,10 @@ int i2d_ASN1_BOOLEAN(ASN1_BOOLEAN a, unsigned char **outp) { - CBB cbb; - if (!CBB_init(&cbb, 3) || // - !CBB_add_asn1_bool(&cbb, a != ASN1_BOOLEAN_FALSE)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/3, outp, [&](CBB *cbb) -> bool { + return CBB_add_asn1_bool(cbb, a != ASN1_BOOLEAN_FALSE); + }); } ASN1_BOOLEAN d2i_ASN1_BOOLEAN(ASN1_BOOLEAN *out, const unsigned char **inp, diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_gentm.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_gentm.cc index dbbbf99e9..645b136a1 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_gentm.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_gentm.cc @@ -36,6 +36,23 @@ int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) { return 1; } +int asn1_parse_generalized_time(CBS *cbs, ASN1_GENERALIZEDTIME *out, + CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_GENERALIZEDTIME : tag; + CBS child; + if (!CBS_get_asn1(cbs, &child, tag) || + !CBS_parse_generalized_time(&child, nullptr, + /*allow_timezone_offset=*/0)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + if (!ASN1_STRING_set(out, CBS_data(&child), CBS_len(&child))) { + return 0; + } + out->type = V_ASN1_GENERALIZEDTIME; + return 1; +} + int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) { return asn1_generalizedtime_to_tm(NULL, d); } diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_int.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_int.cc index 53a28aedf..5a3eaf07e 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_int.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_int.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include "../internal.h" #include "internal.h" @@ -146,32 +147,13 @@ int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) { return len; } -ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp, - long len) { - // This function can handle lengths up to INT_MAX - 1, but the rest of the - // legacy ASN.1 code mixes integer types, so avoid exposing it to - // ASN1_INTEGERS with larger lengths. - if (len < 0 || len > INT_MAX / 2) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); - return NULL; - } - - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); +static int asn1_parse_integer_contents(bssl::Span in, + ASN1_INTEGER *out) { + CBS cbs = in; int is_negative; if (!CBS_is_valid_asn1_integer(&cbs, &is_negative)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); - return NULL; - } - - ASN1_INTEGER *ret = NULL; - if (out == NULL || *out == NULL) { - ret = ASN1_INTEGER_new(); - if (ret == NULL) { - return NULL; - } - } else { - ret = *out; + return 0; } // Convert to |ASN1_INTEGER|'s sign-and-magnitude representation. First, @@ -192,33 +174,75 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp, } } - if (!ASN1_STRING_set(ret, CBS_data(&cbs), CBS_len(&cbs))) { - goto err; + if (!ASN1_STRING_set(out, CBS_data(&cbs), CBS_len(&cbs))) { + return 0; } if (is_negative) { - ret->type = V_ASN1_NEG_INTEGER; - negate_twos_complement(ret->data, ret->length); + out->type = V_ASN1_NEG_INTEGER; + negate_twos_complement(out->data, out->length); } else { - ret->type = V_ASN1_INTEGER; + out->type = V_ASN1_INTEGER; } // The value should be minimally-encoded. - assert(ret->length == 0 || ret->data[0] != 0); + assert(out->length == 0 || out->data[0] != 0); // Zero is not negative. - assert(!is_negative || ret->length > 0); + assert(!is_negative || out->length > 0); + return 1; +} + +int asn1_parse_integer(CBS *cbs, ASN1_INTEGER *out, CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_INTEGER : tag; + CBS child; + if (!CBS_get_asn1(cbs, &child, tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + return asn1_parse_integer_contents(child, out); +} + +int asn1_parse_enumerated(CBS *cbs, ASN1_ENUMERATED *out, CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_ENUMERATED : tag; + if (!asn1_parse_integer(cbs, out, tag)) { + return 0; + } + // Fix the type value. + out->type = + (out->type & V_ASN1_NEG) ? V_ASN1_NEG_ENUMERATED : V_ASN1_ENUMERATED; + return 1; +} + +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp, + long len) { + if (len < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); + return nullptr; + } + + ASN1_INTEGER *ret = nullptr; + if (out == nullptr || *out == nullptr) { + ret = ASN1_INTEGER_new(); + if (ret == nullptr) { + return nullptr; + } + } else { + ret = *out; + } + + if (!asn1_parse_integer_contents(bssl::Span(*inp, len), ret)) { + if (ret != nullptr && (out == nullptr || *out != ret)) { + ASN1_INTEGER_free(ret); + } + return nullptr; + } *inp += len; - if (out != NULL) { + if (out != nullptr) { *out = ret; } return ret; -err: - if (ret != NULL && (out == NULL || *out != ret)) { - ASN1_INTEGER_free(ret); - } - return NULL; } int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t v) { diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_object.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_object.cc index e6e97d6d5..3ed780276 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_object.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_object.cc @@ -27,26 +27,27 @@ #include "internal.h" -int i2d_ASN1_OBJECT(const ASN1_OBJECT *in, unsigned char **outp) { +int asn1_marshal_object(CBB *out, const ASN1_OBJECT *in, CBS_ASN1_TAG tag) { if (in == NULL) { OPENSSL_PUT_ERROR(ASN1, ERR_R_PASSED_NULL_PARAMETER); - return -1; + return 0; } if (in->length <= 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); - return -1; + return 0; } - CBB cbb, child; - if (!CBB_init(&cbb, (size_t)in->length + 2) || - !CBB_add_asn1(&cbb, &child, CBS_ASN1_OBJECT) || - !CBB_add_bytes(&child, in->data, in->length)) { - CBB_cleanup(&cbb); - return -1; - } + tag = tag == 0 ? CBS_ASN1_OBJECT : tag; + return CBB_add_asn1_element(out, tag, in->data, in->length); +} - return CBB_finish_i2d(&cbb, outp); +int i2d_ASN1_OBJECT(const ASN1_OBJECT *in, unsigned char **outp) { + return bssl::I2DFromCBB( + /*initial_capacity=*/static_cast(in->length) + 2, outp, + [&](CBB *cbb) -> bool { + return asn1_marshal_object(cbb, in, /*tag=*/0); + }); } int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) { @@ -90,53 +91,48 @@ int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) { ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp, long len) { - if (len < 0) { - return NULL; - } - - CBS cbs, child; - CBS_init(&cbs, *inp, (size_t)len); - if (!CBS_get_asn1(&cbs, &child, CBS_ASN1_OBJECT)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); - return NULL; - } - - const uint8_t *contents = CBS_data(&child); - ASN1_OBJECT *ret = c2i_ASN1_OBJECT(out, &contents, CBS_len(&child)); - if (ret != NULL) { - // |c2i_ASN1_OBJECT| should have consumed the entire input. - assert(CBS_data(&cbs) == contents); - *inp = CBS_data(&cbs); - } - return ret; + return bssl::D2IFromCBS(out, inp, len, [](CBS *cbs) -> ASN1_OBJECT * { + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_OBJECT)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return nullptr; + } + const uint8_t *contents = CBS_data(&child); + return c2i_ASN1_OBJECT(nullptr, &contents, CBS_len(&child)); + }); } ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp, long len) { - if (len < 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); - return NULL; - } - - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - if (!CBS_is_valid_asn1_oid(&cbs)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); - return NULL; - } + return bssl::D2IFromCBS(out, inp, len, [](CBS *cbs) -> ASN1_OBJECT * { + if (!CBS_is_valid_asn1_oid(cbs)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return nullptr; + } + ASN1_OBJECT *ret = + ASN1_OBJECT_create(NID_undef, CBS_data(cbs), CBS_len(cbs), + /*sn=*/nullptr, /*ln=*/nullptr); + if (ret != nullptr) { + // |c2i_ASN1_OBJECT| consumes its whole input on success. + BSSL_CHECK(CBS_skip(cbs, CBS_len(cbs))); + } + return ret; + }); +} - ASN1_OBJECT *ret = ASN1_OBJECT_create(NID_undef, *inp, (size_t)len, - /*sn=*/NULL, /*ln=*/NULL); - if (ret == NULL) { - return NULL; +ASN1_OBJECT *asn1_parse_object(CBS *cbs, CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_OBJECT : tag; + CBS child; + if (!CBS_get_asn1(cbs, &child, tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return nullptr; } - - if (out != NULL) { - ASN1_OBJECT_free(*out); - *out = ret; + if (!CBS_is_valid_asn1_oid(&child)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return nullptr; } - *inp += len; // All bytes were consumed. - return ret; + return ASN1_OBJECT_create(NID_undef, CBS_data(&child), CBS_len(&child), + /*sn=*/nullptr, /*ln=*/nullptr); } ASN1_OBJECT *ASN1_OBJECT_new(void) { diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_strnid.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_strnid.cc index 0cd7663f4..61007f3a4 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_strnid.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_strnid.cc @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -129,7 +131,7 @@ static const ASN1_STRING_TABLE *asn1_string_table_get(int nid) { ASN1_STRING_TABLE key; key.nid = nid; const ASN1_STRING_TABLE *tbl = reinterpret_cast( - bsearch(&key, tbl_standard, OPENSSL_ARRAY_SIZE(tbl_standard), + bsearch(&key, tbl_standard, std::size(tbl_standard), sizeof(ASN1_STRING_TABLE), table_cmp_void)); if (tbl != NULL) { return tbl; @@ -202,5 +204,5 @@ void ASN1_STRING_TABLE_cleanup(void) {} void asn1_get_string_table_for_testing(const ASN1_STRING_TABLE **out_ptr, size_t *out_len) { *out_ptr = tbl_standard; - *out_len = OPENSSL_ARRAY_SIZE(tbl_standard); + *out_len = std::size(tbl_standard); } diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_time.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_time.cc index a0ac63462..2d9db622b 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_time.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_time.cc @@ -222,3 +222,19 @@ int ASN1_TIME_to_posix(const ASN1_TIME *t, int64_t *out_time) { } return OPENSSL_tm_to_posix(&tm, out_time); } + +int asn1_parse_time(CBS *cbs, ASN1_TIME *out, int allow_utc_timezone_offset) { + if (CBS_peek_asn1_tag(cbs, CBS_ASN1_UTCTIME)) { + return asn1_parse_utc_time(cbs, out, /*tag=*/0, allow_utc_timezone_offset); + } + return asn1_parse_generalized_time(cbs, out, /*tag=*/0); +} + +int asn1_marshal_time(CBB *cbb, const ASN1_TIME *in) { + if (in->type != V_ASN1_UTCTIME && in->type != V_ASN1_GENERALIZEDTIME) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); + return 0; + } + return asn1_marshal_octet_string(cbb, in, + static_cast(in->type)); +} diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_type.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_type.cc index bebe0f906..9423ed0e1 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_type.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_type.cc @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -170,3 +171,220 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) { return result; } + +int asn1_parse_any(CBS *cbs, ASN1_TYPE *out) { + CBS_ASN1_TAG tag; + CBS elem; + size_t header_len; + if (!CBS_get_any_asn1_element(cbs, &elem, &tag, &header_len)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + + // Handle the non-string types. + if (tag == CBS_ASN1_OBJECT) { + bssl::UniquePtr obj(asn1_parse_object(&elem, /*tag=*/0)); + if (obj == nullptr) { + return 0; + } + ASN1_TYPE_set(out, V_ASN1_OBJECT, obj.release()); + return 1; + } + if (tag == CBS_ASN1_NULL) { + if (CBS_len(&elem) != header_len) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + ASN1_TYPE_set(out, V_ASN1_NULL, nullptr); + return 1; + } + if (tag == CBS_ASN1_BOOLEAN) { + int b; + if (!CBS_get_asn1_bool(&elem, &b)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + // V_ASN1_BOOLEAN will interpret the pointer as null for false and any + // arbitrary non-null pointer for true. + ASN1_TYPE_set(out, V_ASN1_BOOLEAN, b ? out : nullptr); + return 1; + } + + // All other cases are handled identically to the string-based ANY parser. + bssl::UniquePtr str(ASN1_STRING_new()); + if (str == nullptr || !asn1_parse_any_as_string(&elem, str.get())) { + return 0; + } + asn1_type_set0_string(out, str.release()); + return 1; +} + +int asn1_parse_any_as_string(CBS *cbs, ASN1_STRING *out) { + CBS_ASN1_TAG tag; + CBS elem; + size_t header_len; + if (!CBS_get_any_asn1_element(cbs, &elem, &tag, &header_len)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + + // Reject unexpectedly constructed or primitive universal types, rather than + // encoding them as an opaque |V_ASN1_OTHER|. As of X.680 (02/2021), tag + // numbers 0-36 have been allocated, except 15. Of these, only 8 (EXTERNAL), + // 11 (EMBEDDED PDV), 16 (SEQUENCE), 17 (SET), and 29 (CHARACTER STRING) are + // constructed. + const CBS_ASN1_TAG tag_class = (tag & CBS_ASN1_CLASS_MASK); + const CBS_ASN1_TAG number = tag & CBS_ASN1_TAG_NUMBER_MASK; + if (tag_class == CBS_ASN1_UNIVERSAL && number <= 36 && number != 15) { + const bool is_constructed = (tag & CBS_ASN1_CONSTRUCTED) != 0; + if (number == V_ASN1_EXTERNAL || number == 11 /* EMBEDDED PDV */ || + number == V_ASN1_SEQUENCE || number == V_ASN1_SET || + number == 29 /* CHARACTER STRING*/) { + if (!is_constructed) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); + return 0; + } + } else { + if (is_constructed) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); + return 0; + } + } + } + + // Historically, parsing high universal tag numbers made OpenSSL's + // |ASN1_STRING| representation ambiguous. We've since fixed this with + // |V_ASN1_OTHER| but, for now, continue to enforce the limit. + if (tag_class == CBS_ASN1_UNIVERSAL && number > V_ASN1_MAX_UNIVERSAL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + + // These types are just parsed as |V_ASN1_OTHER| here. Check the contents + // before the generic |V_ASN1_OTHER| path. + CBS body = elem; + BSSL_CHECK(CBS_skip(&body, header_len)); + switch (tag) { + case CBS_ASN1_OBJECT: + if (!CBS_is_valid_asn1_oid(&body)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return 0; + } + break; + case CBS_ASN1_NULL: + if (CBS_len(&body) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); + return 0; + } + break; + case CBS_ASN1_BOOLEAN: { + uint8_t v; + if (!CBS_get_u8(&body, &v) || CBS_len(&body) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + return 0; + } + if (v != 0 && v != 0xff) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + break; + } + } + + switch (tag) { + case CBS_ASN1_INTEGER: + return asn1_parse_integer(&elem, out, tag); + case CBS_ASN1_ENUMERATED: + return asn1_parse_enumerated(&elem, out, tag); + case CBS_ASN1_BITSTRING: + return asn1_parse_bit_string(&elem, out, tag); + case CBS_ASN1_UNIVERSALSTRING: + return asn1_parse_universal_string(&elem, out, tag); + case CBS_ASN1_BMPSTRING: + return asn1_parse_bmp_string(&elem, out, tag); + case CBS_ASN1_UTF8STRING: + return asn1_parse_utf8_string(&elem, out, tag); + case CBS_ASN1_UTCTIME: + // TODO(crbug.com/42290221): Reject timezone offsets here. We have no + // known cases where UTCTime inside ANY needs accept invalid timezones. + return asn1_parse_utc_time(&elem, out, tag, /*allow_timezone_offset=*/1); + case CBS_ASN1_GENERALIZEDTIME: + return asn1_parse_generalized_time(&elem, out, tag); + case CBS_ASN1_OCTETSTRING: + case CBS_ASN1_T61STRING: + case CBS_ASN1_IA5STRING: + case CBS_ASN1_NUMERICSTRING: + case CBS_ASN1_PRINTABLESTRING: + case CBS_ASN1_VIDEOTEXSTRING: + case CBS_ASN1_GRAPHICSTRING: + case CBS_ASN1_VISIBLESTRING: + case CBS_ASN1_GENERALSTRING: + // T61String is parsed as Latin-1, so all byte strings are valid. The + // others we currently do not enforce. + // + // TODO(crbug.com/42290290): Enforce the encoding of the other string + // types. + if (!asn1_parse_octet_string(&elem, out, tag)) { + return 0; + } + out->type = static_cast(tag); + return 1; + default: + // All unrecognized types, or types that cannot be represented as + // |ASN1_STRING|, are represented as the whole element. + if (!ASN1_STRING_set(out, CBS_data(&elem), CBS_len(&elem))) { + return 0; + } + if (tag == CBS_ASN1_SEQUENCE) { + out->type = V_ASN1_SEQUENCE; + } else if (tag == CBS_ASN1_SET) { + out->type = V_ASN1_SET; + } else { + out->type = V_ASN1_OTHER; + } + return 1; + } +} + +int asn1_marshal_any(CBB *out, const ASN1_TYPE *in) { + switch (in->type) { + case V_ASN1_OBJECT: + return asn1_marshal_object(out, in->value.object, /*tag=*/0); + case V_ASN1_NULL: + return CBB_add_asn1_element(out, CBS_ASN1_NULL, nullptr, 0); + case V_ASN1_BOOLEAN: + return CBB_add_asn1_bool(out, in->value.boolean != ASN1_BOOLEAN_FALSE); + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + return asn1_marshal_integer(out, in->value.integer, + static_cast(in->type)); + case V_ASN1_BIT_STRING: + return asn1_marshal_bit_string(out, in->value.bit_string, /*tag=*/0); + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + return asn1_marshal_octet_string(out, in->value.asn1_string, + static_cast(in->type)); + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + case V_ASN1_OTHER: + // These three types store the whole TLV as contents. + return CBB_add_bytes(out, ASN1_STRING_get0_data(in->value.asn1_string), + ASN1_STRING_length(in->value.asn1_string)); + default: + // |ASN1_TYPE|s can have type -1 when default-constructed. + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); + return 0; + } +} diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/a_utctm.cc b/Sources/CCryptoBoringSSL/crypto/asn1/a_utctm.cc index bedf96fe2..b2452116d 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/a_utctm.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/a_utctm.cc @@ -37,6 +37,22 @@ int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d, return 1; } +int asn1_parse_utc_time(CBS *cbs, ASN1_UTCTIME *out, CBS_ASN1_TAG tag, + int allow_timezone_offset) { + tag = tag == 0 ? CBS_ASN1_UTCTIME : tag; + CBS child; + if (!CBS_get_asn1(cbs, &child, tag) || + !CBS_parse_utc_time(&child, nullptr, allow_timezone_offset)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + if (!ASN1_STRING_set(out, CBS_data(&child), CBS_len(&child))) { + return 0; + } + out->type = V_ASN1_UTCTIME; + return 1; +} + int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) { return asn1_utctime_to_tm(NULL, d, /*allow_timezone_offset=*/1); } diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/asn1_lib.cc b/Sources/CCryptoBoringSSL/crypto/asn1/asn1_lib.cc index aeb3660b3..6efa45028 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/asn1_lib.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/asn1_lib.cc @@ -295,11 +295,21 @@ ASN1_STRING *ASN1_STRING_type_new(int type) { return ret; } +void asn1_string_init(ASN1_STRING *str, int type) { + OPENSSL_memset(str, 0, sizeof(ASN1_STRING)); + str->type = type; +} + +void asn1_string_cleanup(ASN1_STRING *str) { + OPENSSL_free(str->data); + str->data = nullptr; +} + void ASN1_STRING_free(ASN1_STRING *str) { if (str == NULL) { return; } - OPENSSL_free(str->data); + asn1_string_cleanup(str); OPENSSL_free(str); } @@ -353,3 +363,70 @@ unsigned char *ASN1_STRING_data(ASN1_STRING *str) { return str->data; } const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *str) { return str->data; } + +int asn1_parse_octet_string(CBS *cbs, ASN1_STRING *out, CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_OCTETSTRING : tag; + CBS child; + if (!CBS_get_asn1(cbs, &child, tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + if (!ASN1_STRING_set(out, CBS_data(&child), CBS_len(&child))) { + return 0; + } + out->type = V_ASN1_OCTET_STRING; + return 1; +} + +int asn1_marshal_octet_string(CBB *out, const ASN1_STRING *in, + CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_OCTETSTRING : tag; + return CBB_add_asn1_element(out, tag, ASN1_STRING_get0_data(in), + ASN1_STRING_length(in)); +} + +static int asn1_parse_character_string(CBS *cbs, ASN1_STRING *out, + CBS_ASN1_TAG tag, int str_type, + int (*get_char)(CBS *cbs, uint32_t *), + int bad_char_err) { + CBS child; + if (!CBS_get_asn1(cbs, &child, tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + CBS copy = child; + while (CBS_len(©) != 0) { + uint32_t c; + if (!get_char(©, &c)) { + OPENSSL_PUT_ERROR(ASN1, bad_char_err); + return 0; + } + } + if (!ASN1_STRING_set(out, CBS_data(&child), CBS_len(&child))) { + return 0; + } + out->type = str_type; + return 1; +} + +int asn1_parse_bmp_string(CBS *cbs, ASN1_BMPSTRING *out, CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_BMPSTRING : tag; + return asn1_parse_character_string(cbs, out, tag, V_ASN1_BMPSTRING, + &CBS_get_ucs2_be, + ASN1_R_INVALID_BMPSTRING); +} + +int asn1_parse_universal_string(CBS *cbs, ASN1_UNIVERSALSTRING *out, + CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_UNIVERSALSTRING : tag; + return asn1_parse_character_string(cbs, out, tag, V_ASN1_UNIVERSALSTRING, + &CBS_get_utf32_be, + ASN1_R_INVALID_UNIVERSALSTRING); +} + +int asn1_parse_utf8_string(CBS *cbs, ASN1_UNIVERSALSTRING *out, + CBS_ASN1_TAG tag) { + tag = tag == 0 ? CBS_ASN1_UTF8STRING : tag; + return asn1_parse_character_string(cbs, out, tag, V_ASN1_UTF8STRING, + &CBS_get_utf8, ASN1_R_INVALID_UTF8STRING); +} diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/internal.h b/Sources/CCryptoBoringSSL/crypto/asn1/internal.h index 7c1576b51..5b8c63b50 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/asn1/internal.h @@ -48,7 +48,8 @@ OPENSSL_EXPORT int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from, const struct tm *to); -// Internal ASN1 structures and functions: not for application use + +// Object identifiers. // These are used internally in the ASN1_OBJECT to keep track of // whether the names and data need to be free()ed @@ -72,6 +73,130 @@ struct asn1_object_st { ASN1_OBJECT *ASN1_OBJECT_new(void); +// asn1_parse_object parses a DER-encoded ASN.1 OBJECT IDENTIFIER from |cbs| and +// write the result to |out|. If |tag| is non-zero, the value is implicitly +// tagged with |tag|. On success, it returns a newly-allocated |ASN1_OBJECT| +// with the result and advances |cbs| past the parsed element. +// +// TODO(crbug.com/boringssl/414361735): This should return a bssl::UniquePtr, +// but cannot until it is made C++ linkage. +ASN1_OBJECT *asn1_parse_object(CBS *cbs, CBS_ASN1_TAG tag); + +// asn1_marshal_object marshals |in| as a DER-encoded, ASN.1 OBJECT IDENTIFIER +// and writes the result to |out|. It returns one on success and zero on error. +// If |tag| is non-zero, the tag is replaced with |tag|. +int asn1_marshal_object(CBB *out, const ASN1_OBJECT *in, CBS_ASN1_TAG tag); + + +// Strings. + +// asn1_is_printable returns one if |value| is a valid Unicode codepoint for an +// ASN.1 PrintableString, and zero otherwise. +int asn1_is_printable(uint32_t value); + +// asn1_string_init initializes |str|, which may be uninitialized, with type +// |type|. +void asn1_string_init(ASN1_STRING *str, int type); + +// asn1_string_cleanup releases memory associated with |str|'s value, without +// freeing |str| itself. +void asn1_string_cleanup(ASN1_STRING *str); + +// asn1_bit_string_length returns the number of bytes in |str| and sets +// |*out_padding_bits| to the number of padding bits. +// +// This function should be used instead of |ASN1_STRING_length| to correctly +// handle the non-|ASN1_STRING_FLAG_BITS_LEFT| case. +int asn1_bit_string_length(const ASN1_BIT_STRING *str, + uint8_t *out_padding_bits); + +// The following functions parse a DER-encoded ASN.1 value of the specified +// type from |cbs| and write the result to |*out|. If |tag| is non-zero, the +// value is implicitly tagged with |tag|. On success, they return one and +// advance |cbs| past the parsed element. On entry, |*out| must contain an +// |ASN1_STRING| in some valid state. +int asn1_parse_bit_string(CBS *cbs, ASN1_BIT_STRING *out, CBS_ASN1_TAG tag); +int asn1_parse_integer(CBS *cbs, ASN1_INTEGER *out, CBS_ASN1_TAG tag); +int asn1_parse_enumerated(CBS *cbs, ASN1_ENUMERATED *out, CBS_ASN1_TAG tag); +int asn1_parse_octet_string(CBS *cbs, ASN1_STRING *out, CBS_ASN1_TAG tag); +int asn1_parse_bmp_string(CBS *cbs, ASN1_BMPSTRING *out, CBS_ASN1_TAG tag); +int asn1_parse_universal_string(CBS *cbs, ASN1_UNIVERSALSTRING *out, + CBS_ASN1_TAG tag); +int asn1_parse_utf8_string(CBS *cbs, ASN1_UNIVERSALSTRING *out, + CBS_ASN1_TAG tag); +int asn1_parse_generalized_time(CBS *cbs, ASN1_GENERALIZEDTIME *out, + CBS_ASN1_TAG tag); +int asn1_parse_utc_time(CBS *cbs, ASN1_UTCTIME *out, CBS_ASN1_TAG tag, + int allow_timezone_offset); + +// asn1_parse_bit_string_with_bad_length behaves like |asn1_parse_bit_string| +// but tolerates BER non-minimal, definite lengths. +int asn1_parse_bit_string_with_bad_length(CBS *cbs, ASN1_BIT_STRING *out); + +// asn1_marshal_bit_string marshals |in| as a DER-encoded, ASN.1 BIT STRING and +// writes the result to |out|. It returns one on success and zero on error. If +// |tag| is non-zero, the tag is replaced with |tag|. +int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in, + CBS_ASN1_TAG tag); + +// asn1_marshal_integer marshals |in| as a DER-encoded, ASN.1 INTEGER and writes +// the result to |out|. It returns one on success and zero on error. If |tag| is +// non-zero, the tag is replaced with |tag|. This can also be used to marshal an +// ASN.1 ENUMERATED value by overriding the tag. +int asn1_marshal_integer(CBB *out, const ASN1_INTEGER *in, CBS_ASN1_TAG tag); + +// asn1_marshal_octet_string marshals |in| as a DER-encoded, ASN.1 OCTET STRING +// and writes the result to |out|. It returns one on success and zero on error. +// If |tag| is non-zero, the tag is replaced with |tag|. +// +// This function may be used to marshal other string-based universal types whose +// encoding is that of an implicitly-tagged OCTET STRING, e.g. UTF8String. +int asn1_marshal_octet_string(CBB *out, const ASN1_STRING *in, + CBS_ASN1_TAG tag); + +OPENSSL_EXPORT int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d, + int allow_timezone_offset); +OPENSSL_EXPORT int asn1_generalizedtime_to_tm(struct tm *tm, + const ASN1_GENERALIZEDTIME *d); + +int asn1_parse_time(CBS *cbs, ASN1_TIME *out, int allow_utc_timezone_offset); +int asn1_marshal_time(CBB *cbb, const ASN1_TIME *in); + + +// The ASN.1 ANY type. + +// asn1_type_value_as_pointer returns |a|'s value in pointer form. This is +// usually the value object but, for BOOLEAN values, is 0 or 0xff cast to +// a pointer. +const void *asn1_type_value_as_pointer(const ASN1_TYPE *a); + +// asn1_type_set0_string sets |a|'s value to the object represented by |str| and +// takes ownership of |str|. +void asn1_type_set0_string(ASN1_TYPE *a, ASN1_STRING *str); + +// asn1_type_cleanup releases memory associated with |a|'s value, without +// freeing |a| itself. +void asn1_type_cleanup(ASN1_TYPE *a); + +// asn1_parse_any parses a DER-encoded ASN.1 value of any type from |cbs| and +// writes the result to |*out|. On success, it advances |cbs| past the parsed +// element and returns one. On entry, |*out| must contain an |ASN1_TYPE| in some +// valid state. +int asn1_parse_any(CBS *cbs, ASN1_TYPE *out); + +// asn1_parse_any_as_string behaves like |asn1_parse_any| but represents the +// value as an |ASN1_STRING|. Types which are not represented with +// |ASN1_STRING|, such as |ASN1_OBJECT|, are represented with type +// |V_ASN1_OTHER|. +int asn1_parse_any_as_string(CBS *cbs, ASN1_STRING *out); + +// asn1_marshal_any marshals |in| as a DER-encoded ASN.1 value and writes the +// result to |out|. It returns one on success and zeron on error. +int asn1_marshal_any(CBB *out, const ASN1_TYPE *in); + + +// Support structures for the template-based encoder. + // ASN1_ENCODING is used to save the received encoding of an ASN.1 type. This // avoids problems with invalid encodings that break signatures. typedef struct ASN1_ENCODING_st { @@ -79,16 +204,8 @@ typedef struct ASN1_ENCODING_st { uint8_t *enc; // len is the length of |enc|. If zero, there is no saved encoding. size_t len; - // buf, if non-NULL, is the |CRYPTO_BUFFER| that |enc| points into. If NULL, - // |enc| must be released with |OPENSSL_free|. - CRYPTO_BUFFER *buf; } ASN1_ENCODING; -OPENSSL_EXPORT int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d, - int allow_timezone_offset); -OPENSSL_EXPORT int asn1_generalizedtime_to_tm(struct tm *tm, - const ASN1_GENERALIZEDTIME *d); - int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); @@ -97,14 +214,12 @@ void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); // ASN1_item_ex_d2i parses |len| bytes from |*in| as a structure of type |it| // and writes the result to |*pval|. If |tag| is non-negative, |it| is // implicitly tagged with the tag specified by |tag| and |aclass|. If |opt| is -// non-zero, the value is optional. If |buf| is non-NULL, |*in| must point into -// |buf|. +// non-zero, the value is optional. // // This function returns one and advances |*in| if an object was successfully // parsed, -1 if an optional value was successfully skipped, and zero on error. int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, int tag, int aclass, char opt, - CRYPTO_BUFFER *buf); + const ASN1_ITEM *it, int tag, int aclass, char opt); // ASN1_item_ex_i2d encodes |*pval| as a value of type |it| to |out| under the // i2d output convention. It returns a non-zero length on success and -1 on @@ -150,47 +265,11 @@ int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, // returns one on success and zero on error. If |buf| is non-NULL, |in| must // point into |buf|. int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t inlen, - const ASN1_ITEM *it, CRYPTO_BUFFER *buf); + const ASN1_ITEM *it); // asn1_encoding_clear clears the cached encoding in |enc|. void asn1_encoding_clear(ASN1_ENCODING *enc); -// asn1_type_value_as_pointer returns |a|'s value in pointer form. This is -// usually the value object but, for BOOLEAN values, is 0 or 0xff cast to -// a pointer. -const void *asn1_type_value_as_pointer(const ASN1_TYPE *a); - -// asn1_type_set0_string sets |a|'s value to the object represented by |str| and -// takes ownership of |str|. -void asn1_type_set0_string(ASN1_TYPE *a, ASN1_STRING *str); - -// asn1_type_cleanup releases memory associated with |a|'s value, without -// freeing |a| itself. -void asn1_type_cleanup(ASN1_TYPE *a); - -// asn1_is_printable returns one if |value| is a valid Unicode codepoint for an -// ASN.1 PrintableString, and zero otherwise. -int asn1_is_printable(uint32_t value); - -// asn1_bit_string_length returns the number of bytes in |str| and sets -// |*out_padding_bits| to the number of padding bits. -// -// This function should be used instead of |ASN1_STRING_length| to correctly -// handle the non-|ASN1_STRING_FLAG_BITS_LEFT| case. -int asn1_bit_string_length(const ASN1_BIT_STRING *str, - uint8_t *out_padding_bits); - -// asn1_marshal_bit_string marshals |in| as a DER-encoded, ASN.1 BIT STRING and -// writes the result to |out|. It returns one on success and zero on error. If -// |tag| is non-zero, the tag is replaced with |tag|. -int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in, - CBS_ASN1_TAG tag); - -// asn1_marshal_integer marshals |in| as a DER-encoded, ASN.1 INTEGER and writes -// the result to |out|. It returns one on success and zero on error. If |tag| is -// non-zero, the tag is replaced with |tag|. -int asn1_marshal_integer(CBB *out, const ASN1_INTEGER *in, CBS_ASN1_TAG tag); - typedef struct { int nid; long minsize; @@ -210,8 +289,18 @@ typedef ASN1_VALUE *ASN1_d2i_func(ASN1_VALUE **a, const unsigned char **in, long length); typedef int ASN1_i2d_func(ASN1_VALUE *a, unsigned char **in); -typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, int opt, ASN1_TLC *ctx); +// An ASN1_ex_parse function should parse a value from |cbs| and set |*pval| to +// the result. It should return one on success and zero on failure. If |opt| is +// non-zero, the field may be optional. If an optional element is missing, the +// function should return one and consume zero bytes from |cbs|. +// +// If |opt| is non-zero, the function can assume that |*pval| is nullptr on +// entry. Otherwise, |*pval| may either be nullptr, or the result of +// |ASN1_ex_new_func|. The function may either write into the existing object, +// if any, or unconditionally make a new one. (The existing object comes from +// tasn_new.cc recursively filling in objects before parsing into them.) +typedef int ASN1_ex_parse(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, + int opt); typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it); @@ -221,10 +310,57 @@ typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); typedef struct ASN1_EXTERN_FUNCS_st { ASN1_ex_new_func *asn1_ex_new; ASN1_ex_free_func *asn1_ex_free; - ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_parse *asn1_ex_parse; ASN1_ex_i2d *asn1_ex_i2d; } ASN1_EXTERN_FUNCS; +#define IMPLEMENT_EXTERN_ASN1_SIMPLE(name, new_func, free_func, parse_func, \ + i2d_func) \ + static int name##_new_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { \ + *pval = (ASN1_VALUE *)new_func(); \ + return *pval != nullptr; \ + } \ + \ + static void name##_free_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { \ + free_func((name *)*pval); \ + *pval = nullptr; \ + } \ + \ + static int name##_parse_cb(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, \ + int opt) { \ + if (opt && !CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) { \ + return 1; \ + } \ + \ + if ((*pval == nullptr && !name##_new_cb(pval, it)) || \ + !parse_func(cbs, (name *)*pval)) { \ + return 0; \ + } \ + return 1; \ + } \ + \ + static int name##_i2d_cb(ASN1_VALUE **pval, unsigned char **out, \ + const ASN1_ITEM *it) { \ + return i2d_func((name *)*pval, out); \ + } \ + \ + static const ASN1_EXTERN_FUNCS name##_extern_funcs = { \ + name##_new_cb, name##_free_cb, name##_parse_cb, name##_i2d_cb}; \ + \ + IMPLEMENT_EXTERN_ASN1(name, name##_extern_funcs) + +// ASN1_TIME is an |ASN1_ITEM| whose ASN.1 type is X.509 Time (RFC 5280) and C +// type is |ASN1_TIME*|. +DECLARE_ASN1_ITEM(ASN1_TIME) + +// DIRECTORYSTRING is an |ASN1_ITEM| whose ASN.1 type is X.509 DirectoryString +// (RFC 5280) and C type is |ASN1_STRING*|. +DECLARE_ASN1_ITEM(DIRECTORYSTRING) + +// DISPLAYTEXT is an |ASN1_ITEM| whose ASN.1 type is X.509 DisplayText (RFC +// 5280) and C type is |ASN1_STRING*|. +DECLARE_ASN1_ITEM(DISPLAYTEXT) + // ASN1_ANY_AS_STRING is an |ASN1_ITEM| with ASN.1 type ANY and C type // |ASN1_STRING*|. Types which are not represented with |ASN1_STRING|, such as // |ASN1_OBJECT|, are represented with type |V_ASN1_OTHER|. diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/tasn_dec.cc b/Sources/CCryptoBoringSSL/crypto/asn1/tasn_dec.cc index 690083665..acc3cf661 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/tasn_dec.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/tasn_dec.cc @@ -39,18 +39,16 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - CRYPTO_BUFFER *buf, int depth); + int depth); static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - CRYPTO_BUFFER *buf, int depth); -static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, - int utype, const ASN1_ITEM *it); + int depth); static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, char opt); static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, - char opt, CRYPTO_BUFFER *buf, int depth); + char opt, int depth); unsigned long ASN1_tag2bit(int tag) { switch (tag) { @@ -91,25 +89,6 @@ unsigned long ASN1_tag2bit(int tag) { } } -static int is_supported_universal_type(int tag, int aclass) { - if (aclass != V_ASN1_UNIVERSAL) { - return 0; - } - return tag == V_ASN1_OBJECT || tag == V_ASN1_NULL || tag == V_ASN1_BOOLEAN || - tag == V_ASN1_BIT_STRING || tag == V_ASN1_INTEGER || - tag == V_ASN1_ENUMERATED || tag == V_ASN1_OCTET_STRING || - tag == V_ASN1_NUMERICSTRING || tag == V_ASN1_PRINTABLESTRING || - tag == V_ASN1_T61STRING || tag == V_ASN1_VIDEOTEXSTRING || - tag == V_ASN1_IA5STRING || tag == V_ASN1_UTCTIME || - tag == V_ASN1_GENERALIZEDTIME || tag == V_ASN1_GRAPHICSTRING || - tag == V_ASN1_VISIBLESTRING || tag == V_ASN1_GENERALSTRING || - tag == V_ASN1_UNIVERSALSTRING || tag == V_ASN1_BMPSTRING || - tag == V_ASN1_UTF8STRING || tag == V_ASN1_SET || - tag == V_ASN1_SEQUENCE; -} - -// Macro to initialize and invalidate the cache - // Decode an ASN1 item, this currently behaves just like a standard 'd2i' // function. 'in' points to a buffer to read the data from, in future we // will have more advanced versions that can input data a piece at a time and @@ -119,7 +98,7 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it) { ASN1_VALUE *ret = NULL; if (asn1_item_ex_d2i(&ret, in, len, it, /*tag=*/-1, /*aclass=*/0, /*opt=*/0, - /*buf=*/NULL, /*depth=*/0) <= 0) { + /*depth=*/0) <= 0) { // Clean up, in case the caller left a partial object. // // TODO(davidben): I don't think it can leave one, but the codepaths below @@ -149,7 +128,7 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, - char opt, CRYPTO_BUFFER *buf, int depth) { + char opt, int depth) { const ASN1_TEMPLATE *tt, *errtt = NULL; const unsigned char *p = NULL, *q; unsigned char oclass; @@ -161,10 +140,9 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, if (!pval) { return 0; } - - if (buf != NULL) { - assert(CRYPTO_BUFFER_data(buf) <= *in && - *in + len <= CRYPTO_BUFFER_data(buf) + CRYPTO_BUFFER_len(buf)); + if (len < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); + goto err; } // Bound |len| to comfortably fit in an int. Lengths in this module often @@ -189,11 +167,9 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); goto err; } - return asn1_template_ex_d2i(pval, in, len, it->templates, opt, buf, - depth); + return asn1_template_ex_d2i(pval, in, len, it->templates, opt, depth); } return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt); - break; case ASN1_ITYPE_MSTRING: // It never makes sense for multi-strings to have implicit tagging, so @@ -239,7 +215,18 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, } const ASN1_EXTERN_FUNCS *ef = reinterpret_cast(it->funcs); - return ef->asn1_ex_d2i(pval, in, len, it, opt, NULL); + CBS cbs; + CBS_init(&cbs, *in, len); + CBS copy = cbs; + if (!ef->asn1_ex_parse(pval, &cbs, it, opt)) { + goto err; + } + *in = CBS_data(&cbs); + // Check whether the function skipped an optional element. + // + // TODO(crbug.com/42290418): Switch the rest of this function to + // |asn1_ex_parse|'s calling convention. + return CBS_len(&cbs) == CBS_len(©) ? -1 : 1; } case ASN1_ITYPE_CHOICE: { @@ -274,7 +261,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { pchptr = asn1_get_field_ptr(pval, tt); // We mark field as OPTIONAL so its absence can be recognised. - ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, buf, depth); + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, depth); // If field not present, try the next one if (ret == -1) { continue; @@ -380,7 +367,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, } // attempt to read in field, allowing each to be OPTIONAL - ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, buf, depth); + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, depth); if (!ret) { errtt = seqtt; goto err; @@ -419,7 +406,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, } } // Save encoding - if (!asn1_enc_save(pval, *in, p - *in, it, buf)) { + if (!asn1_enc_save(pval, *in, p - *in, it)) { goto auxerr; } if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) { @@ -445,10 +432,8 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, } int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, int tag, int aclass, char opt, - CRYPTO_BUFFER *buf) { - return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, buf, - /*depth=*/0); + const ASN1_ITEM *it, int tag, int aclass, char opt) { + return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, /*depth=*/0); } // Templates are handled with two separate functions. One handles any @@ -456,7 +441,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, const ASN1_TEMPLATE *tt, char opt, - CRYPTO_BUFFER *buf, int depth) { + int depth) { int aclass; int ret; long len; @@ -488,7 +473,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, return 0; } // We've found the field so it can't be OPTIONAL now - ret = asn1_template_noexp_d2i(val, &p, len, tt, /*opt=*/0, buf, depth); + ret = asn1_template_noexp_d2i(val, &p, len, tt, /*opt=*/0, depth); if (!ret) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); return 0; @@ -501,7 +486,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, goto err; } } else { - return asn1_template_noexp_d2i(val, in, inlen, tt, opt, buf, depth); + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, depth); } *in = p; @@ -514,7 +499,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - CRYPTO_BUFFER *buf, int depth) { + int depth) { int aclass; int ret; const unsigned char *p; @@ -572,7 +557,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, const unsigned char *q = p; skfield = NULL; if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), - /*tag=*/-1, /*aclass=*/0, /*opt=*/0, buf, depth)) { + /*tag=*/-1, /*aclass=*/0, /*opt=*/0, depth)) { + ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item)); OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); goto err; } @@ -585,7 +571,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, } else if (flags & ASN1_TFLG_IMPTAG) { // IMPLICIT tagging ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, - aclass, opt, buf, depth); + aclass, opt, depth); if (!ret) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); goto err; @@ -595,7 +581,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, } else { // Nothing special ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), /*tag=*/-1, - /*aclass=*/0, opt, buf, depth); + /*aclass=*/0, opt, depth); if (!ret) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); goto err; @@ -612,306 +598,211 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, return 0; } +// TODO(crbug.com/42290418): Switch the whole file to use a CBS-based calling +// convention. +static int asn1_d2i_ex_primitive_cbs(ASN1_VALUE **pval, CBS *cbs, + const ASN1_ITEM *it, int tag, int aclass, + char opt); + +// asn1_d2i_ex_primitive returns one on success, zero on error, and -1 if an +// optional value was skipped. static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, const ASN1_ITEM *it, int tag, int aclass, char opt) { - int ret = 0, utype; - long plen; - char cst; - const unsigned char *p; - const unsigned char *cont = NULL; - long len; - if (!pval) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL); - return 0; // Should never happen + CBS cbs; + CBS_init(&cbs, *in, inlen); + int ret = asn1_d2i_ex_primitive_cbs(pval, &cbs, it, tag, aclass, opt); + if (ret <= 0) { + return ret; + } + *in = CBS_data(&cbs); + return 1; +} + +static ASN1_STRING *ensure_string(ASN1_VALUE **pval) { + if (*pval) { + return (ASN1_STRING *)*pval; } + ASN1_STRING *str = ASN1_STRING_new(); + if (str == nullptr) { + return nullptr; + } + *pval = (ASN1_VALUE *)str; + return str; +} + +static int asn1_d2i_ex_primitive_cbs(ASN1_VALUE **pval, CBS *cbs, + const ASN1_ITEM *it, int tag, int aclass, + char opt) { + // Historically, |it->funcs| for primitive types contained an + // |ASN1_PRIMITIVE_FUNCS| table of callbacks. + assert(it->funcs == NULL); + int utype; assert(it->itype == ASN1_ITYPE_PRIMITIVE || it->itype == ASN1_ITYPE_MSTRING); if (it->itype == ASN1_ITYPE_MSTRING) { + // MSTRING passes utype in |tag|, normally used for implicit tagging. utype = tag; tag = -1; } else { utype = it->utype; } + // Handle ANY types. if (utype == V_ASN1_ANY || utype == V_ASN1_ANY_AS_STRING) { - // If type is ANY need to figure out type from tag - unsigned char oclass; if (tag >= 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY); return 0; } - if (opt) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY); - return 0; - } - const int is_string = utype == V_ASN1_ANY_AS_STRING; - p = *in; - ret = asn1_check_tlen(&plen, &utype, &oclass, &cst, &p, inlen, -1, 0, 0); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - return 0; - } - if (!is_supported_universal_type(utype, oclass)) { - utype = V_ASN1_OTHER; + if (opt && CBS_len(cbs) == 0) { + return -1; // Omitted OPTIONAL value. } - // These three types are not represented as |ASN1_STRING|, so they must be - // parsed separately and then treated as an opaque |V_ASN1_OTHER|. - if (is_string && (utype == V_ASN1_OBJECT || utype == V_ASN1_NULL || - utype == V_ASN1_BOOLEAN)) { - if (cst) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); - return 0; - } - CBS cbs; - CBS_init(&cbs, p, plen); - if (utype == V_ASN1_OBJECT && !CBS_is_valid_asn1_oid(&cbs)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); - return 0; - } - if (utype == V_ASN1_NULL && CBS_len(&cbs) != 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); + } + if (utype == V_ASN1_ANY) { + ASN1_TYPE *typ; + if (!*pval) { + typ = ASN1_TYPE_new(); + if (typ == NULL) { return 0; } - if (utype == V_ASN1_BOOLEAN) { - if (CBS_len(&cbs) != 1) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); - return 0; - } - uint8_t v = CBS_data(&cbs)[0]; - if (v != 0 && v != 0xff) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); - return 0; - } - } - utype = V_ASN1_OTHER; + *pval = (ASN1_VALUE *)typ; + } else { + typ = (ASN1_TYPE *)*pval; + } + return asn1_parse_any(cbs, typ); + } + if (utype == V_ASN1_ANY_AS_STRING) { + ASN1_STRING *str = ensure_string(pval); + if (str == nullptr) { + return 0; } + return asn1_parse_any_as_string(cbs, str); } + + // Convert the crypto/asn1 tag into a CBS one. if (tag == -1) { tag = utype; aclass = V_ASN1_UNIVERSAL; } - p = *in; - // Check header - ret = asn1_check_tlen(&plen, NULL, NULL, &cst, &p, inlen, tag, aclass, opt); - if (!ret) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); - return 0; - } else if (ret == -1) { - return -1; - } - ret = 0; - // SEQUENCE, SET and "OTHER" are left in encoded form - if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || - (utype == V_ASN1_OTHER)) { - // SEQUENCE and SET must be constructed - if (utype != V_ASN1_OTHER && !cst) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); - return 0; - } - cont = *in; - len = p - cont + plen; - p += plen; - } else if (cst) { - // This parser historically supported BER constructed strings. We no - // longer do and will gradually tighten this parser into a DER - // parser. BER types should use |CBS_asn1_ber_to_der|. - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); - return 0; - } else { - cont = p; - len = plen; - p += plen; + // All edge cases of |utype| should have been handled already. |utype| is now + // either a primitive |ASN1_ITEM|, handled by |DECLARE_ASN1_ITEM|, or a + // multistring option with a corresponding |B_ASN1_*| constant. + assert(utype >= 0 && utype <= V_ASN1_MAX_UNIVERSAL); + CBS_ASN1_TAG cbs_tag = + (static_cast(aclass) << CBS_ASN1_TAG_SHIFT) | + static_cast(tag); + if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET) { + cbs_tag |= CBS_ASN1_CONSTRUCTED; } - // We now have content length and type: translate into a structure - if (!asn1_ex_c2i(pval, cont, len, utype, it)) { - goto err; + if (opt && !CBS_peek_asn1_tag(cbs, cbs_tag)) { + return -1; // Omitted OPTIONAL value. } - *in = p; - ret = 1; -err: - return ret; -} - -// Translate ASN1 content octets into a structure - -static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, - int utype, const ASN1_ITEM *it) { - ASN1_VALUE **opval = NULL; - ASN1_STRING *stmp; - ASN1_TYPE *typ = NULL; - int ret = 0; - ASN1_INTEGER **tint; - - // Historically, |it->funcs| for primitive types contained an - // |ASN1_PRIMITIVE_FUNCS| table of callbacks. - assert(it->funcs == NULL); - - // If ANY type clear type and set pointer to internal value - if (it->utype == V_ASN1_ANY) { - if (!*pval) { - typ = ASN1_TYPE_new(); - if (typ == NULL) { - goto err; + // Handle non-|ASN1_STRING| types. + switch (utype) { + case V_ASN1_OBJECT: { + bssl::UniquePtr obj(asn1_parse_object(cbs, cbs_tag)); + if (obj == nullptr) { + return 0; } - *pval = (ASN1_VALUE *)typ; - } else { - typ = (ASN1_TYPE *)*pval; - } - - if (utype != typ->type) { - ASN1_TYPE_set(typ, utype, NULL); + ASN1_OBJECT_free((ASN1_OBJECT *)*pval); + *pval = (ASN1_VALUE *)obj.release(); + return 1; } - opval = pval; - pval = &typ->value.asn1_value; - } - - // If implementing a type that is not represented in |ASN1_STRING|, the - // |V_ASN1_ANY_AS_STRING| logic must be modified to redirect it to - // |V_ASN1_OTHER|. - switch (utype) { - case V_ASN1_OBJECT: - if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) { - goto err; + case V_ASN1_NULL: { + CBS null; + if (!CBS_get_asn1(cbs, &null, cbs_tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; } - break; - - case V_ASN1_NULL: - if (len) { + if (CBS_len(&null) != 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); - goto err; + return 0; } *pval = (ASN1_VALUE *)1; - break; - - case V_ASN1_BOOLEAN: - if (len != 1) { + return 1; + } + case V_ASN1_BOOLEAN: { + CBS child; + if (!CBS_get_asn1(cbs, &child, cbs_tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + // TODO(crbug.com/42290221): Reject invalid BOOLEAN encodings and just + // call |CBS_get_asn1_bool|. + if (CBS_len(&child) != 1) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); - goto err; - } else { - ASN1_BOOLEAN *tbool; - tbool = (ASN1_BOOLEAN *)pval; - *tbool = *cont; + return 0; } - break; + ASN1_BOOLEAN *tbool; + tbool = (ASN1_BOOLEAN *)pval; + *tbool = CBS_data(&child)[0]; + return 1; + } + } - case V_ASN1_BIT_STRING: - if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) { - goto err; - } - break; + // All other types as an |ASN1_STRING| representation. + ASN1_STRING *str = ensure_string(pval); + if (str == nullptr) { + return 0; + } + switch (utype) { + case V_ASN1_BIT_STRING: + return asn1_parse_bit_string(cbs, str, cbs_tag); case V_ASN1_INTEGER: + return asn1_parse_integer(cbs, str, cbs_tag); case V_ASN1_ENUMERATED: - tint = (ASN1_INTEGER **)pval; - if (!c2i_ASN1_INTEGER(tint, &cont, len)) { - goto err; - } - // Fixup type to match the expected form - (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); - break; - + return asn1_parse_enumerated(cbs, str, cbs_tag); + case V_ASN1_UNIVERSALSTRING: + return asn1_parse_universal_string(cbs, str, cbs_tag); + case V_ASN1_BMPSTRING: + return asn1_parse_bmp_string(cbs, str, cbs_tag); + case V_ASN1_UTF8STRING: + return asn1_parse_utf8_string(cbs, str, cbs_tag); + case V_ASN1_UTCTIME: + // TODO(crbug.com/42290221): Reject timezone offsets. We need to parse + // invalid timestamps in |X509| objects, but that parser no longer uses + // this code. + return asn1_parse_utc_time(cbs, str, cbs_tag, + /*allow_timezone_offset=*/1); + case V_ASN1_GENERALIZEDTIME: + return asn1_parse_generalized_time(cbs, str, cbs_tag); case V_ASN1_OCTET_STRING: case V_ASN1_NUMERICSTRING: case V_ASN1_PRINTABLESTRING: case V_ASN1_T61STRING: case V_ASN1_VIDEOTEXSTRING: case V_ASN1_IA5STRING: - case V_ASN1_UTCTIME: - case V_ASN1_GENERALIZEDTIME: case V_ASN1_GRAPHICSTRING: case V_ASN1_VISIBLESTRING: case V_ASN1_GENERALSTRING: - case V_ASN1_UNIVERSALSTRING: - case V_ASN1_BMPSTRING: - case V_ASN1_UTF8STRING: - case V_ASN1_OTHER: - case V_ASN1_SET: - case V_ASN1_SEQUENCE: { - CBS cbs; - CBS_init(&cbs, cont, (size_t)len); - if (utype == V_ASN1_BMPSTRING) { - while (CBS_len(&cbs) != 0) { - uint32_t c; - if (!CBS_get_ucs2_be(&cbs, &c)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING); - goto err; - } - } - } - if (utype == V_ASN1_UNIVERSALSTRING) { - while (CBS_len(&cbs) != 0) { - uint32_t c; - if (!CBS_get_utf32_be(&cbs, &c)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING); - goto err; - } - } - } - if (utype == V_ASN1_UTF8STRING) { - while (CBS_len(&cbs) != 0) { - uint32_t c; - if (!CBS_get_utf8(&cbs, &c)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING); - goto err; - } - } - } - if (utype == V_ASN1_UTCTIME) { - if (!CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT); - goto err; - } - } - if (utype == V_ASN1_GENERALIZEDTIME) { - if (!CBS_parse_generalized_time(&cbs, NULL, - /*allow_timezone_offset=*/0)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT); - goto err; - } - } - // TODO(https://crbug.com/boringssl/427): Check other string types. - - // All based on ASN1_STRING and handled the same - if (!*pval) { - stmp = ASN1_STRING_type_new(utype); - if (!stmp) { - goto err; - } - *pval = (ASN1_VALUE *)stmp; - } else { - stmp = (ASN1_STRING *)*pval; - stmp->type = utype; + // T61String is parsed as Latin-1, so all byte strings are valid. The + // others we currently do not enforce. + // + // TODO(crbug.com/42290290): Enforce the encoding of the other string + // types. + if (!asn1_parse_octet_string(cbs, str, cbs_tag)) { + return 0; } - if (!ASN1_STRING_set(stmp, cont, len)) { - ASN1_STRING_free(stmp); - *pval = NULL; - goto err; + str->type = utype; + return 1; + case V_ASN1_SEQUENCE: { + // Save the entire element in the string. + CBS elem; + if (!CBS_get_asn1_element(cbs, &elem, cbs_tag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; } - break; + str->type = V_ASN1_SEQUENCE; + return ASN1_STRING_set(str, CBS_data(&elem), CBS_len(&elem)); } - default: OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); - goto err; - } - // If ASN1_ANY and NULL type fix up value - if (typ && (utype == V_ASN1_NULL)) { - typ->value.ptr = NULL; - } - - ret = 1; -err: - if (!ret) { - ASN1_TYPE_free(typ); - if (opval) { - *opval = NULL; + return 0; } - } - return ret; } // Check an ASN1 tag and length: a bit like ASN1_get_object but it diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/tasn_typ.cc b/Sources/CCryptoBoringSSL/crypto/asn1/tasn_typ.cc index 313abb814..05526b5f7 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/tasn_typ.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/tasn_typ.cc @@ -19,6 +19,9 @@ #include "internal.h" +// TODO(crbug.com/42290417): While we need |ASN1_ITEM|s, the exposed new, free, +// i2d, and d2i functions should call the underlying implementations directly. + #define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ IMPLEMENT_ASN1_TYPE(sname) \ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(sname, sname, sname) \ diff --git a/Sources/CCryptoBoringSSL/crypto/asn1/tasn_utl.cc b/Sources/CCryptoBoringSSL/crypto/asn1/tasn_utl.cc index ebdbe7362..12e9d195a 100644 --- a/Sources/CCryptoBoringSSL/crypto/asn1/tasn_utl.cc +++ b/Sources/CCryptoBoringSSL/crypto/asn1/tasn_utl.cc @@ -94,7 +94,6 @@ void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) { if (enc) { enc->enc = NULL; enc->len = 0; - enc->buf = NULL; } } @@ -106,7 +105,7 @@ void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { } int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t in_len, - const ASN1_ITEM *it, CRYPTO_BUFFER *buf) { + const ASN1_ITEM *it) { ASN1_ENCODING *enc; enc = asn1_get_enc_ptr(pval, it); if (!enc) { @@ -114,17 +113,9 @@ int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t in_len, } asn1_encoding_clear(enc); - if (buf != NULL) { - assert(CRYPTO_BUFFER_data(buf) <= in && - in + in_len <= CRYPTO_BUFFER_data(buf) + CRYPTO_BUFFER_len(buf)); - CRYPTO_BUFFER_up_ref(buf); - enc->buf = buf; - enc->enc = (uint8_t *)in; - } else { - enc->enc = reinterpret_cast(OPENSSL_memdup(in, in_len)); - if (!enc->enc) { - return 0; - } + enc->enc = reinterpret_cast(OPENSSL_memdup(in, in_len)); + if (!enc->enc) { + return 0; } enc->len = in_len; @@ -132,14 +123,9 @@ int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t in_len, } void asn1_encoding_clear(ASN1_ENCODING *enc) { - if (enc->buf != NULL) { - CRYPTO_BUFFER_free(enc->buf); - } else { - OPENSSL_free(enc->enc); - } + OPENSSL_free(enc->enc); enc->enc = NULL; enc->len = 0; - enc->buf = NULL; } int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, diff --git a/Sources/CCryptoBoringSSL/crypto/blake2/blake2.cc b/Sources/CCryptoBoringSSL/crypto/blake2/blake2.cc index 71125f7b4..fd9e3995c 100644 --- a/Sources/CCryptoBoringSSL/crypto/blake2/blake2.cc +++ b/Sources/CCryptoBoringSSL/crypto/blake2/blake2.cc @@ -16,6 +16,8 @@ #include +#include + #include "../internal.h" // https://tools.ietf.org/html/rfc7693#section-2.6 @@ -99,7 +101,7 @@ static void blake2b_transform(BLAKE2B_CTX *b2b, blake2b_load(block, s[15])); } - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(b2b->h); i++) { + for (size_t i = 0; i < std::size(b2b->h); i++) { b2b->h[i] ^= v[i]; b2b->h[i] ^= v[i + 8]; } diff --git a/Sources/CCryptoBoringSSL/crypto/bytestring/internal.h b/Sources/CCryptoBoringSSL/crypto/bytestring/internal.h index b0d55f018..19b76ab51 100644 --- a/Sources/CCryptoBoringSSL/crypto/bytestring/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/bytestring/internal.h @@ -15,12 +15,14 @@ #ifndef OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H #define OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H -#include +#include +#include +#include + +#include -#if defined(__cplusplus) -extern "C" { -#endif +extern "C" { // CBS_asn1_ber_to_der reads a BER element from |in|. If it finds // indefinite-length elements or constructed strings then it converts the BER @@ -66,9 +68,53 @@ OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out, // This function may be used to help implement legacy i2d ASN.1 functions. int CBB_finish_i2d(CBB *cbb, uint8_t **outp); - -#if defined(__cplusplus) } // extern C -#endif + +BSSL_NAMESPACE_BEGIN + +// D2IFromCBS takes a functor of type |Unique(CBS*)| and implements the d2i +// calling convention. For compatibility with functions that don't tag their +// return value (e.g. public APIs), |T*(CBS)| is also accepted. The callback can +// assume that the |CBS|'s length fits in |long|. The callback should not access +// |out|, |inp|, or |len| directly. +template +inline T *D2IFromCBS(T **out, const uint8_t **inp, long len, CBSFunc func) { + static_assert(std::is_invocable_v); + static_assert( + std::is_same_v, UniquePtr> || + std::is_same_v, T *>); + if (len < 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); + return nullptr; + } + CBS cbs; + CBS_init(&cbs, *inp, len); + UniquePtr ret(func(&cbs)); + if (ret == nullptr) { + return nullptr; + } + if (out != nullptr) { + UniquePtr free_out(*out); + *out = ret.get(); + } + *inp = CBS_data(&cbs); + return ret.release(); +} + +// I2DFromCBB takes a functor of type |bool(CBB*)| and implements the i2d +// calling convention. It internally makes a |CBB| with the specified initial +// capacity. The callback should not access |outp| directly. +template +inline int I2DFromCBB(size_t initial_capacity, uint8_t **outp, CBBFunc func) { + static_assert(std::is_invocable_v); + static_assert(std::is_same_v, bool>); + ScopedCBB cbb; + if (!CBB_init(cbb.get(), initial_capacity) || !func(cbb.get())) { + return -1; + } + return CBB_finish_i2d(cbb.get(), outp); +} + +BSSL_NAMESPACE_END #endif // OPENSSL_HEADER_CRYPTO_BYTESTRING_INTERNAL_H diff --git a/Sources/CCryptoBoringSSL/crypto/cipher/e_aesctrhmac.cc b/Sources/CCryptoBoringSSL/crypto/cipher/e_aesctrhmac.cc index 2ff4614a7..1a3ec9694 100644 --- a/Sources/CCryptoBoringSSL/crypto/cipher/e_aesctrhmac.cc +++ b/Sources/CCryptoBoringSSL/crypto/cipher/e_aesctrhmac.cc @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include "../fipsmodule/aes/internal.h" #include "../fipsmodule/cipher/internal.h" diff --git a/Sources/CCryptoBoringSSL/crypto/cipher/e_tls.cc b/Sources/CCryptoBoringSSL/crypto/cipher/e_tls.cc index a418df43f..3c18c91cd 100644 --- a/Sources/CCryptoBoringSSL/crypto/cipher/e_tls.cc +++ b/Sources/CCryptoBoringSSL/crypto/cipher/e_tls.cc @@ -31,7 +31,7 @@ typedef struct { EVP_CIPHER_CTX cipher_ctx; - HMAC_CTX hmac_ctx; + HMAC_CTX *hmac_ctx; // mac_key is the portion of the key used for the MAC. It is retained // separately for the constant-time CBC code. uint8_t mac_key[EVP_MAX_MD_SIZE]; @@ -51,15 +51,14 @@ static_assert(alignof(union evp_aead_ctx_st_state) >= alignof(AEAD_TLS_CTX), static void aead_tls_cleanup(EVP_AEAD_CTX *ctx) { AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)&ctx->state; EVP_CIPHER_CTX_cleanup(&tls_ctx->cipher_ctx); - HMAC_CTX_cleanup(&tls_ctx->hmac_ctx); + HMAC_CTX_free(tls_ctx->hmac_ctx); } static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len, enum evp_aead_direction_t dir, const EVP_CIPHER *cipher, const EVP_MD *md, char implicit_iv) { - if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH && - tag_len != EVP_MD_size(md)) { + if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH && tag_len != EVP_MD_size(md)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE); return 0; } @@ -72,11 +71,15 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t mac_key_len = EVP_MD_size(md); size_t enc_key_len = EVP_CIPHER_key_length(cipher); assert(mac_key_len + enc_key_len + - (implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len); + (implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == + key_len); AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)&ctx->state; + tls_ctx->hmac_ctx = HMAC_CTX_new(); + if (!tls_ctx->hmac_ctx) { + return 0; + } EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx); - HMAC_CTX_init(&tls_ctx->hmac_ctx); assert(mac_key_len <= EVP_MAX_MD_SIZE); OPENSSL_memcpy(tls_ctx->mac_key, key, mac_key_len); tls_ctx->mac_key_len = (uint8_t)mac_key_len; @@ -85,7 +88,7 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len], implicit_iv ? &key[mac_key_len + enc_key_len] : NULL, dir == evp_aead_seal) || - !HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) { + !HMAC_Init_ex(tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) { aead_tls_cleanup(ctx); return 0; } @@ -99,7 +102,7 @@ static size_t aead_tls_tag_len(const EVP_AEAD_CTX *ctx, const size_t in_len, assert(extra_in_len == 0); const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)&ctx->state; - const size_t hmac_len = HMAC_size(&tls_ctx->hmac_ctx); + const size_t hmac_len = HMAC_size(tls_ctx->hmac_ctx); if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE) { // The NULL cipher. return hmac_len; @@ -160,11 +163,11 @@ static int aead_tls_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, // in-place. uint8_t mac[EVP_MAX_MD_SIZE]; unsigned mac_len; - if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || - !HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) || - !HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) || - !HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) || - !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) { + if (!HMAC_Init_ex(tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || + !HMAC_Update(tls_ctx->hmac_ctx, ad, ad_len) || + !HMAC_Update(tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) || + !HMAC_Update(tls_ctx->hmac_ctx, in, in_len) || + !HMAC_Final(tls_ctx->hmac_ctx, mac, &mac_len)) { return 0; } @@ -187,7 +190,8 @@ static int aead_tls_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, // block from encrypting the input and split the result between |out| and // |out_tag|. Then feed the rest. - const size_t early_mac_len = (block_size - (in_len % block_size)) % block_size; + const size_t early_mac_len = + (block_size - (in_len % block_size)) % block_size; if (early_mac_len != 0) { assert(len + block_size - early_mac_len == in_len); uint8_t buf[EVP_MAX_BLOCK_LENGTH]; @@ -245,7 +249,7 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, return 0; } - if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) { + if (in_len < HMAC_size(tls_ctx->hmac_ctx)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } @@ -303,7 +307,7 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, if (!EVP_tls_cbc_remove_padding( &padding_ok, &data_plus_mac_len, out, total, EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx), - HMAC_size(&tls_ctx->hmac_ctx))) { + HMAC_size(tls_ctx->hmac_ctx))) { // Publicly invalid. This can be rejected in non-constant time. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; @@ -313,9 +317,9 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, data_plus_mac_len = total; // |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has // already been checked against the MAC size at the top of the function. - assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx)); + assert(data_plus_mac_len >= HMAC_size(tls_ctx->hmac_ctx)); } - size_t data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx); + size_t data_len = data_plus_mac_len - HMAC_size(tls_ctx->hmac_ctx); // At this point, if the padding is valid, the first |data_plus_mac_len| bytes // after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is @@ -335,14 +339,14 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, uint8_t record_mac_tmp[EVP_MAX_MD_SIZE]; uint8_t *record_mac; if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && - EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx.md)) { - if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx.md, mac, &mac_len, + EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx->md)) { + if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx->md, mac, &mac_len, ad_fixed, out, data_len, total, tls_ctx->mac_key, tls_ctx->mac_key_len)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; } - assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx)); + assert(mac_len == HMAC_size(tls_ctx->hmac_ctx)); record_mac = record_mac_tmp; EVP_tls_cbc_copy_mac(record_mac, mac_len, out, data_plus_mac_len, total); @@ -352,15 +356,15 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE); unsigned mac_len_u; - if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || - !HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) || - !HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) || - !HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) { + if (!HMAC_Init_ex(tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) || + !HMAC_Update(tls_ctx->hmac_ctx, ad_fixed, ad_len) || + !HMAC_Update(tls_ctx->hmac_ctx, out, data_len) || + !HMAC_Final(tls_ctx->hmac_ctx, mac, &mac_len_u)) { return 0; } mac_len = mac_len_u; - assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx)); + assert(mac_len == HMAC_size(tls_ctx->hmac_ctx)); record_mac = &out[data_len]; } diff --git a/Sources/CCryptoBoringSSL/crypto/cipher/get_cipher.cc b/Sources/CCryptoBoringSSL/crypto/cipher/get_cipher.cc index 24a6e3183..43934b950 100644 --- a/Sources/CCryptoBoringSSL/crypto/cipher/get_cipher.cc +++ b/Sources/CCryptoBoringSSL/crypto/cipher/get_cipher.cc @@ -55,17 +55,17 @@ static const struct { }; const EVP_CIPHER *EVP_get_cipherbynid(int nid) { - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCiphers); i++) { - if (kCiphers[i].nid == nid) { - return kCiphers[i].func(); + for (const auto &cipher : kCiphers) { + if (cipher.nid == nid) { + return cipher.func(); } } - return NULL; + return nullptr; } const EVP_CIPHER *EVP_get_cipherbyname(const char *name) { - if (name == NULL) { - return NULL; + if (name == nullptr) { + return nullptr; } // This is not a name used by OpenSSL, but tcpdump registers it with @@ -75,11 +75,11 @@ const EVP_CIPHER *EVP_get_cipherbyname(const char *name) { name = "des-ede3-cbc"; } - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCiphers); i++) { - if (OPENSSL_strcasecmp(kCiphers[i].name, name) == 0) { - return kCiphers[i].func(); + for (const auto &cipher : kCiphers) { + if (OPENSSL_strcasecmp(cipher.name, name) == 0) { + return cipher.func(); } } - return NULL; + return nullptr; } diff --git a/Sources/CCryptoBoringSSL/crypto/cipher/internal.h b/Sources/CCryptoBoringSSL/crypto/cipher/internal.h index a4106a4f1..6fde1487e 100644 --- a/Sources/CCryptoBoringSSL/crypto/cipher/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/cipher/internal.h @@ -19,6 +19,7 @@ #include #include +#include #include "../internal.h" @@ -129,7 +130,7 @@ union chacha20_poly1305_seal_data { } out; }; -#if (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \ +#if (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \ !defined(OPENSSL_NO_ASM) static_assert(sizeof(union chacha20_poly1305_open_data) == 48, diff --git a/Sources/CCryptoBoringSSL/crypto/conf/conf.cc b/Sources/CCryptoBoringSSL/crypto/conf/conf.cc index f29418e98..94931bf7c 100644 --- a/Sources/CCryptoBoringSSL/crypto/conf/conf.cc +++ b/Sources/CCryptoBoringSSL/crypto/conf/conf.cc @@ -623,6 +623,8 @@ int CONF_modules_load_file(const char *filename, const char *appname, return 1; } +void CONF_modules_unload(int all) {} + void CONF_modules_free(void) {} void OPENSSL_config(const char *config_name) {} diff --git a/Sources/CCryptoBoringSSL/crypto/crypto.cc b/Sources/CCryptoBoringSSL/crypto/crypto.cc index 773e351d0..d94b6f810 100644 --- a/Sources/CCryptoBoringSSL/crypto/crypto.cc +++ b/Sources/CCryptoBoringSSL/crypto/crypto.cc @@ -137,6 +137,8 @@ void ENGINE_load_builtin_engines(void) {} int ENGINE_register_all_complete(void) { return 1; } +void ENGINE_cleanup(void) {} + void OPENSSL_load_builtin_modules(void) {} int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) { diff --git a/Sources/CCryptoBoringSSL/crypto/curve25519/curve25519.cc b/Sources/CCryptoBoringSSL/crypto/curve25519/curve25519.cc index 5a2bdf65b..c61e31361 100644 --- a/Sources/CCryptoBoringSSL/crypto/curve25519/curve25519.cc +++ b/Sources/CCryptoBoringSSL/crypto/curve25519/curve25519.cc @@ -24,7 +24,7 @@ #include #include -#include +#include #include "../internal.h" #include "internal.h" diff --git a/Sources/CCryptoBoringSSL/crypto/curve25519/spake25519.cc b/Sources/CCryptoBoringSSL/crypto/curve25519/spake25519.cc index b04f875f4..8f890faea 100644 --- a/Sources/CCryptoBoringSSL/crypto/curve25519/spake25519.cc +++ b/Sources/CCryptoBoringSSL/crypto/curve25519/spake25519.cc @@ -17,10 +17,12 @@ #include #include +#include + #include #include #include -#include +#include #include "../fipsmodule/bn/internal.h" #include "../internal.h" @@ -333,18 +335,17 @@ static const scalar kOrder = { // scalar_cmov copies |src| to |dest| if |mask| is all ones. static void scalar_cmov(scalar *dest, const scalar *src, crypto_word_t mask) { bn_select_words(dest->words, mask, src->words, dest->words, - OPENSSL_ARRAY_SIZE(dest->words)); + std::size(dest->words)); } // scalar_double sets |s| to |2×s|. static void scalar_double(scalar *s) { - bn_add_words(s->words, s->words, s->words, OPENSSL_ARRAY_SIZE(s->words)); + bn_add_words(s->words, s->words, s->words, std::size(s->words)); } // scalar_add sets |dest| to |dest| plus |src|. static void scalar_add(scalar *dest, const scalar *src) { - bn_add_words(dest->words, dest->words, src->words, - OPENSSL_ARRAY_SIZE(dest->words)); + bn_add_words(dest->words, dest->words, src->words, std::size(dest->words)); } int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len, diff --git a/Sources/CCryptoBoringSSL/crypto/dh/dh_asn1.cc b/Sources/CCryptoBoringSSL/crypto/dh/dh_asn1.cc index 60fe212c7..3c44926d1 100644 --- a/Sources/CCryptoBoringSSL/crypto/dh/dh_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/dh/dh_asn1.cc @@ -95,29 +95,11 @@ int DH_marshal_parameters(CBB *cbb, const DH *dh) { } DH *d2i_DHparams(DH **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - DH *ret = DH_parse_parameters(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - DH_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, DH_parse_parameters); } int i2d_DHparams(const DH *in, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !DH_marshal_parameters(&cbb, in)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/256, outp, + [&](CBB *cbb) -> bool { return DH_marshal_parameters(cbb, in); }); } diff --git a/Sources/CCryptoBoringSSL/crypto/dh/params.cc b/Sources/CCryptoBoringSSL/crypto/dh/params.cc index 02287926f..35fcf9a09 100644 --- a/Sources/CCryptoBoringSSL/crypto/dh/params.cc +++ b/Sources/CCryptoBoringSSL/crypto/dh/params.cc @@ -17,13 +17,13 @@ #include #include #include +#include #include "../fipsmodule/bn/internal.h" #include "../fipsmodule/dh/internal.h" -static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words, - size_t num_words) { +static BIGNUM *get_params(BIGNUM *ret, bssl::Span words) { BIGNUM *alloc = NULL; if (ret == NULL) { alloc = BN_new(); @@ -33,7 +33,7 @@ static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words, ret = alloc; } - if (!bn_set_words(ret, words, num_words)) { + if (!bn_set_words(ret, words.data(), words.size())) { BN_free(alloc); return NULL; } @@ -56,7 +56,7 @@ BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *ret) { TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); + return get_params(ret, kWords); } BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *ret) { @@ -78,7 +78,7 @@ BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *ret) { TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); + return get_params(ret, kWords); } BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *ret) { @@ -108,7 +108,7 @@ BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *ret) { TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); + return get_params(ret, kWords); } BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *ret) { @@ -146,7 +146,7 @@ BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *ret) { TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); + return get_params(ret, kWords); } BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *ret) { @@ -200,7 +200,7 @@ BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *ret) { TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); + return get_params(ret, kWords); } BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *ret) { @@ -270,7 +270,7 @@ BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *ret) { TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); + return get_params(ret, kWords); } int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, diff --git a/Sources/CCryptoBoringSSL/crypto/digest/digest_extra.cc b/Sources/CCryptoBoringSSL/crypto/digest/digest_extra.cc index d7b0c1a06..ab46cd9d7 100644 --- a/Sources/CCryptoBoringSSL/crypto/digest/digest_extra.cc +++ b/Sources/CCryptoBoringSSL/crypto/digest/digest_extra.cc @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "../asn1/internal.h" #include "../fipsmodule/digest/internal.h" @@ -71,9 +73,9 @@ const EVP_MD *EVP_get_digestbynid(int nid) { return NULL; } - for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) { - if (nid_to_digest_mapping[i].nid == nid) { - return nid_to_digest_mapping[i].md_func(); + for (const auto &mapping : nid_to_digest_mapping) { + if (mapping.nid == nid) { + return mapping.md_func(); } } @@ -101,42 +103,41 @@ static const struct { {{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, NID_sha224}, }; -static const EVP_MD *cbs_to_md(const CBS *cbs) { - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) { - if (CBS_len(cbs) == kMDOIDs[i].oid_len && - OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) == - 0) { - return EVP_get_digestbynid(kMDOIDs[i].nid); +static int cbs_to_digest_nid(const CBS *cbs) { + for (const auto &md : kMDOIDs) { + if (bssl::Span(*cbs) == + bssl::Span(md.oid).first(md.oid_len)) { + return md.nid; } } - - return NULL; + return NID_undef; } const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj) { - // Handle objects with no corresponding OID. Note we don't use |OBJ_obj2nid| - // here to avoid pulling in the OID table. - if (obj->nid != NID_undef) { - return EVP_get_digestbynid(obj->nid); + int nid = obj->nid; + if (nid == NID_undef) { + // Handle objects with no saved NID. Note we don't use |OBJ_obj2nid| here to + // avoid pulling in the OID table. + CBS cbs; + CBS_init(&cbs, OBJ_get0_data(obj), OBJ_length(obj)); + nid = cbs_to_digest_nid(&cbs); } - CBS cbs; - CBS_init(&cbs, OBJ_get0_data(obj), OBJ_length(obj)); - return cbs_to_md(&cbs); + return nid == NID_undef ? nullptr : EVP_get_digestbynid(nid); } -const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) { +int EVP_parse_digest_algorithm_nid(CBS *cbs) { CBS algorithm, oid; if (!CBS_get_asn1(cbs, &algorithm, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) { OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR); - return NULL; + return NID_undef; } - const EVP_MD *ret = cbs_to_md(&oid); - if (ret == NULL) { + int ret = cbs_to_digest_nid(&oid); + if (ret == NID_undef) { OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH); - return NULL; + return NID_undef; } // The parameters, if present, must be NULL. Historically, whether the NULL @@ -149,13 +150,21 @@ const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) { CBS_len(¶m) != 0 || // CBS_len(&algorithm) != 0) { OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR); - return NULL; + return NID_undef; } } return ret; } +const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) { + int nid = EVP_parse_digest_algorithm_nid(cbs); + if (nid == NID_undef) { + return nullptr; + } + return EVP_get_digestbynid(nid); +} + static int marshal_digest_algorithm(CBB *cbb, const EVP_MD *md, bool with_null) { CBB algorithm, oid, null; @@ -198,16 +207,16 @@ int EVP_marshal_digest_algorithm_no_params(CBB *cbb, const EVP_MD *md) { } const EVP_MD *EVP_get_digestbyname(const char *name) { - for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) { - const char *short_name = nid_to_digest_mapping[i].short_name; - const char *long_name = nid_to_digest_mapping[i].long_name; + for (const auto &mapping : nid_to_digest_mapping) { + const char *short_name = mapping.short_name; + const char *long_name = mapping.long_name; if ((short_name && strcmp(short_name, name) == 0) || (long_name && strcmp(long_name, name) == 0)) { - return nid_to_digest_mapping[i].md_func(); + return mapping.md_func(); } } - return NULL; + return nullptr; } static void blake2b256_init(EVP_MD_CTX *ctx) { @@ -230,6 +239,8 @@ static const EVP_MD evp_md_blake2b256 = { const EVP_MD *EVP_blake2b256(void) { return &evp_md_blake2b256; } +static_assert(sizeof(BLAKE2B_CTX) <= EVP_MAX_MD_DATA_SIZE); + static void md4_init(EVP_MD_CTX *ctx) { BSSL_CHECK(MD4_Init(reinterpret_cast(ctx->md_data))); @@ -257,6 +268,9 @@ static const EVP_MD evp_md_md4 = { const EVP_MD *EVP_md4(void) { return &evp_md_md4; } +static_assert(sizeof(MD4_CTX) <= EVP_MAX_MD_DATA_SIZE); + + static void md5_init(EVP_MD_CTX *ctx) { BSSL_CHECK(MD5_Init(reinterpret_cast(ctx->md_data))); } @@ -277,6 +291,9 @@ static const EVP_MD evp_md_md5 = { const EVP_MD *EVP_md5(void) { return &evp_md_md5; } +static_assert(sizeof(MD5_CTX) <= EVP_MAX_MD_DATA_SIZE); + + typedef struct { MD5_CTX md5; SHA_CTX sha1; @@ -312,3 +329,5 @@ const EVP_MD evp_md_md5_sha1 = { }; const EVP_MD *EVP_md5_sha1(void) { return &evp_md_md5_sha1; } + +static_assert(sizeof(MD5_SHA1_CTX) <= EVP_MAX_MD_DATA_SIZE); diff --git a/Sources/CCryptoBoringSSL/crypto/dsa/dsa.cc b/Sources/CCryptoBoringSSL/crypto/dsa/dsa.cc index 778237d3e..cbc382731 100644 --- a/Sources/CCryptoBoringSSL/crypto/dsa/dsa.cc +++ b/Sources/CCryptoBoringSSL/crypto/dsa/dsa.cc @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "../fipsmodule/bn/internal.h" #include "../fipsmodule/dh/internal.h" diff --git a/Sources/CCryptoBoringSSL/crypto/dsa/dsa_asn1.cc b/Sources/CCryptoBoringSSL/crypto/dsa/dsa_asn1.cc index 743f21fdf..08a63413d 100644 --- a/Sources/CCryptoBoringSSL/crypto/dsa/dsa_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/dsa/dsa_asn1.cc @@ -255,113 +255,41 @@ int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) { } DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - DSA_SIG *ret = DSA_SIG_parse(&cbs); - if (ret == NULL) { - return NULL; - } - if (out_sig != NULL) { - DSA_SIG_free(*out_sig); - *out_sig = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out_sig, inp, len, DSA_SIG_parse); } int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !DSA_SIG_marshal(&cbb, in)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/256, outp, + [&](CBB *cbb) -> bool { return DSA_SIG_marshal(cbb, in); }); } DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - DSA *ret = DSA_parse_public_key(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - DSA_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, DSA_parse_public_key); } int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !DSA_marshal_public_key(&cbb, in)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/256, outp, + [&](CBB *cbb) -> bool { return DSA_marshal_public_key(cbb, in); }); } DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - DSA *ret = DSA_parse_private_key(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - DSA_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, DSA_parse_private_key); } int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !DSA_marshal_private_key(&cbb, in)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/256, outp, + [&](CBB *cbb) -> bool { return DSA_marshal_private_key(cbb, in); }); } DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - DSA *ret = DSA_parse_parameters(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - DSA_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, DSA_parse_parameters); } int i2d_DSAparams(const DSA *in, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !DSA_marshal_parameters(&cbb, in)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/256, outp, + [&](CBB *cbb) -> bool { return DSA_marshal_parameters(cbb, in); }); } diff --git a/Sources/CCryptoBoringSSL/crypto/ec/ec_asn1.cc b/Sources/CCryptoBoringSSL/crypto/ec/ec_asn1.cc index e7e4ff339..092e8845b 100644 --- a/Sources/CCryptoBoringSSL/crypto/ec/ec_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/ec/ec_asn1.cc @@ -17,6 +17,9 @@ #include #include +#include +#include + #include #include #include @@ -27,6 +30,7 @@ #include "../bytestring/internal.h" #include "../fipsmodule/ec/internal.h" #include "../internal.h" +#include "internal.h" static const CBS_ASN1_TAG kParametersTag = @@ -34,17 +38,23 @@ static const CBS_ASN1_TAG kParametersTag = static const CBS_ASN1_TAG kPublicKeyTag = CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1; -// TODO(https://crbug.com/boringssl/497): Allow parsers to specify a list of -// acceptable groups, so parsers don't have to pull in all four. -typedef const EC_GROUP *(*ec_group_func)(void); -static const ec_group_func kAllGroups[] = { - &EC_group_p224, - &EC_group_p256, - &EC_group_p384, - &EC_group_p521, -}; +static auto get_all_groups() { + return std::array{ + EC_group_p224(), + EC_group_p256(), + EC_group_p384(), + EC_group_p521(), + }; +} + +EC_KEY *ec_key_parse_private_key( + CBS *cbs, const EC_GROUP *group, + bssl::Span allowed_groups) { + // If a group was supplied externally, no other groups can be parsed. + if (group != nullptr) { + allowed_groups = bssl::Span(&group, 1); + } -EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { CBS ec_private_key, private_key; uint64_t version; if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) || @@ -66,23 +76,31 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); return nullptr; } - const EC_GROUP *inner_group = EC_KEY_parse_parameters(&child); + const EC_GROUP *inner_group = + ec_key_parse_parameters(&child, allowed_groups); if (inner_group == nullptr) { + // If the caller already supplied a group, any explicit group is required + // to match. On mismatch, |ec_key_parse_parameters| will fail to recognize + // any other groups, so remap the error. + if (group != nullptr && + ERR_equals(ERR_peek_last_error(), ERR_LIB_EC, EC_R_UNKNOWN_GROUP)) { + ERR_clear_error(); + OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); + } return nullptr; } - if (group == nullptr) { - group = inner_group; - } else if (EC_GROUP_cmp(group, inner_group, nullptr) != 0) { - // If a group was supplied externally, it must match. - OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); - return nullptr; - } + // Overriding |allowed_groups| above ensures the only returned group will be + // the matching one. + assert(group == nullptr || inner_group == group); + group = inner_group; if (CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); return nullptr; } } + // The group must have been specified either externally, or explicitly in the + // structure. if (group == nullptr) { OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); return nullptr; @@ -151,6 +169,10 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { return ret.release(); } +EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) { + return ec_key_parse_private_key(cbs, group, get_all_groups()); +} + int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key, unsigned enc_flags) { if (key == NULL || key->group == NULL || key->priv_key == NULL) { @@ -296,23 +318,29 @@ static int integers_equal(const CBS *bytes, const BIGNUM *bn) { return CBS_mem_equal(©, buf, CBS_len(©)); } -EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) { +const EC_GROUP *ec_key_parse_curve_name( + CBS *cbs, bssl::Span allowed_groups) { CBS named_curve; if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) { OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); - return NULL; + return nullptr; } // Look for a matching curve. - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) { - const EC_GROUP *group = kAllGroups[i](); - if (CBS_mem_equal(&named_curve, group->oid, group->oid_len)) { - return (EC_GROUP *)group; + for (const EC_GROUP *group : allowed_groups) { + if (named_curve == bssl::Span(group->oid, group->oid_len)) { + return group; } } OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); - return NULL; + return nullptr; +} + +EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) { + // This function only ever returns a static |EC_GROUP|, but currently returns + // a non-const pointer for historical reasons. + return const_cast(ec_key_parse_curve_name(cbs, get_all_groups())); } int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) { @@ -324,9 +352,10 @@ int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) { return CBB_add_asn1_element(cbb, CBS_ASN1_OBJECT, group->oid, group->oid_len); } -EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) { +const EC_GROUP *ec_key_parse_parameters( + CBS *cbs, bssl::Span allowed_groups) { if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) { - return EC_KEY_parse_curve_name(cbs); + return ec_key_parse_curve_name(cbs, allowed_groups); } // OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions @@ -348,8 +377,7 @@ EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) { return nullptr; } - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) { - const EC_GROUP *group = kAllGroups[i](); + for (const EC_GROUP *group : allowed_groups) { if (!integers_equal(&curve.order, EC_GROUP_get0_order(group))) { continue; } @@ -372,13 +400,19 @@ EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) { !integers_equal(&curve.base_y, y.get())) { break; } - return const_cast(group); + return group; } OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); return nullptr; } +EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) { + // This function only ever returns a static |EC_GROUP|, but currently returns + // a non-const pointer for historical reasons. + return const_cast(ec_key_parse_parameters(cbs, get_all_groups())); +} + int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, BN_CTX *ctx) { size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx); @@ -398,52 +432,20 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) { group = EC_KEY_get0_group(*out); } - if (len < 0) { - OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - EC_KEY *ret = EC_KEY_parse_private_key(&cbs, group); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - EC_KEY_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, [&](CBS *cbs) { + return EC_KEY_parse_private_key(cbs, group); + }); } int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/64, outp, [&](CBB *cbb) -> bool { + return EC_KEY_marshal_private_key(cbb, key, EC_KEY_get_enc_flags(key)); + }); } EC_GROUP *d2i_ECPKParameters(EC_GROUP **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - EC_GROUP *ret = EC_KEY_parse_parameters(&cbs); - if (ret == NULL) { - return NULL; - } - - if (out != NULL) { - EC_GROUP_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, EC_KEY_parse_parameters); } int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) { @@ -451,40 +453,24 @@ int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) { OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); return -1; } - - CBB cbb; - if (!CBB_init(&cbb, 0) || // - !EC_KEY_marshal_curve_name(&cbb, group)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/16, outp, + [&](CBB *cbb) -> bool { return EC_KEY_marshal_curve_name(cbb, group); }); } EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - const EC_GROUP *group = EC_KEY_parse_parameters(&cbs); - if (group == NULL) { - return NULL; - } - - EC_KEY *ret = EC_KEY_new(); - if (ret == NULL || !EC_KEY_set_group(ret, group)) { - EC_KEY_free(ret); - return NULL; - } - - if (out_key != NULL) { - EC_KEY_free(*out_key); - *out_key = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS( + out_key, inp, len, [](CBS *cbs) -> bssl::UniquePtr { + const EC_GROUP *group = EC_KEY_parse_parameters(cbs); + if (group == nullptr) { + return nullptr; + } + bssl::UniquePtr ret(EC_KEY_new()); + if (ret == nullptr || !EC_KEY_set_group(ret.get(), group)) { + return nullptr; + } + return ret; + }); } int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) { @@ -492,14 +478,10 @@ int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) { OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); return -1; } - - CBB cbb; - if (!CBB_init(&cbb, 0) || // - !EC_KEY_marshal_curve_name(&cbb, key->group)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/16, outp, [&](CBB *cbb) -> bool { + return EC_KEY_marshal_curve_name(cbb, key->group); + }); } EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) { @@ -529,27 +511,25 @@ int i2o_ECPublicKey(const EC_KEY *key, uint8_t **outp) { OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } - CBB cbb; - if (!CBB_init(&cbb, 0) || // - !EC_POINT_point2cbb(&cbb, key->group, key->pub_key, key->conv_form, - NULL)) { - CBB_cleanup(&cbb); - return -1; - } - int ret = CBB_finish_i2d(&cbb, outp); + // No initial capacity because |EC_POINT_point2cbb| will internally reserve + // the right size in one shot, so it's best to leave this at zero. + int ret = bssl::I2DFromCBB( + /*initial_capacity=*/0, outp, [&](CBB *cbb) -> bool { + return EC_POINT_point2cbb(cbb, key->group, key->pub_key, key->conv_form, + nullptr); + }); // Historically, this function used the wrong return value on error. return ret > 0 ? ret : 0; } size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, size_t max_num_curves) { - if (max_num_curves > OPENSSL_ARRAY_SIZE(kAllGroups)) { - max_num_curves = OPENSSL_ARRAY_SIZE(kAllGroups); - } + auto all = get_all_groups(); + max_num_curves = std::min(all.size(), max_num_curves); for (size_t i = 0; i < max_num_curves; i++) { - const EC_GROUP *group = kAllGroups[i](); + const EC_GROUP *group = all[i]; out_curves[i].nid = group->curve_name; out_curves[i].comment = group->comment; } - return OPENSSL_ARRAY_SIZE(kAllGroups); + return all.size(); } diff --git a/Sources/CCryptoBoringSSL/crypto/ec/internal.h b/Sources/CCryptoBoringSSL/crypto/ec/internal.h index 336c3f298..7409e888b 100644 --- a/Sources/CCryptoBoringSSL/crypto/ec/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/ec/internal.h @@ -17,6 +17,8 @@ #include +#include + #include "../fipsmodule/ec/internal.h" #if defined(__cplusplus) @@ -24,6 +26,31 @@ extern "C" { #endif +// Parsing functions. + +// ec_key_parse_curve_name behaves like |EC_KEY_parse_curve_name| but only +// supports the groups in |allowed_groups|. If no syntax errors were found but +// the group is unknown, it will fail with an error of |EC_R_UNKNOWN_GROUP|. +const EC_GROUP *ec_key_parse_curve_name( + CBS *cbs, bssl::Span allowed_groups); + +// ec_key_parse_parameters behaves like |EC_KEY_parse_parameters| but only +// supports the groups in |allowed_groups|. If no syntax errors were found but +// the group is unknown, it will fail with an error of |EC_R_UNKNOWN_GROUP|. +const EC_GROUP *ec_key_parse_parameters( + CBS *cbs, bssl::Span allowed_groups); + +// ec_key_parse_private_key behaves like |EC_KEY_parse_private_key| but only +// supports the groups in |allowed_groups|. If |group| is non-NULL, +// |allowed_groups| is ignored and instead only |group| is supported. +// +// TODO(crbug.com/boringssl/414361735): This should return a bssl::UniquePtr, +// but cannot until it is made C++ linkage. +EC_KEY *ec_key_parse_private_key( + CBS *cbs, const EC_GROUP *group, + bssl::Span allowed_groups); + + // Hash-to-curve. // // Internal |EC_JACOBIAN| versions of the corresponding public APIs. diff --git a/Sources/CCryptoBoringSSL/crypto/ecdsa/ecdsa_asn1.cc b/Sources/CCryptoBoringSSL/crypto/ecdsa/ecdsa_asn1.cc index b2dd3b259..8c06fcea3 100644 --- a/Sources/CCryptoBoringSSL/crypto/ecdsa/ecdsa_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/ecdsa/ecdsa_asn1.cc @@ -324,28 +324,11 @@ size_t ECDSA_SIG_max_len(size_t order_len) { } ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - ECDSA_SIG_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, ECDSA_SIG_parse); } int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || !ECDSA_SIG_marshal(&cbb, sig)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/64, outp, + [&](CBB *cbb) -> bool { return ECDSA_SIG_marshal(cbb, sig); }); } diff --git a/Sources/CCryptoBoringSSL/crypto/evp/evp.cc b/Sources/CCryptoBoringSSL/crypto/evp/evp.cc index c14565da1..9afa1ff6f 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/evp.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/evp.cc @@ -41,19 +41,10 @@ EVP_PKEY *EVP_PKEY_new(void) { return NULL; } - ret->type = EVP_PKEY_NONE; ret->references = 1; return ret; } -static void free_it(EVP_PKEY *pkey) { - if (pkey->ameth && pkey->ameth->pkey_free) { - pkey->ameth->pkey_free(pkey); - pkey->pkey = NULL; - pkey->type = EVP_PKEY_NONE; - } -} - void EVP_PKEY_free(EVP_PKEY *pkey) { if (pkey == NULL) { return; @@ -63,7 +54,7 @@ void EVP_PKEY_free(EVP_PKEY *pkey) { return; } - free_it(pkey); + evp_pkey_set0(pkey, nullptr, nullptr); OPENSSL_free(pkey); } @@ -80,7 +71,7 @@ int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) { } int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { - if (a->type != b->type) { + if (EVP_PKEY_id(a) != EVP_PKEY_id(b)) { return -1; } @@ -103,9 +94,13 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { } int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { - if (to->type == EVP_PKEY_NONE) { - evp_pkey_set_method(to, from->ameth); - } else if (to->type != from->type) { + if (EVP_PKEY_id(to) == EVP_PKEY_NONE) { + // TODO(crbug.com/42290409): This shouldn't leave |to| in a half-empty state + // on error. The complexity here largely comes from parameterless DSA keys, + // which we no longer support, so this function can probably be trimmed + // down. + evp_pkey_set0(to, from->ameth, nullptr); + } else if (EVP_PKEY_id(to) != EVP_PKEY_id(from)) { OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); return 0; } @@ -128,8 +123,9 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { return from->ameth->param_copy(to, from); } - // TODO(https://crbug.com/boringssl/536): If the algorithm takes no - // parameters, copying them should vacuously succeed. + // TODO(https://crbug.com/42290406): If the algorithm takes no parameters, + // copying them should vacuously succeed. Better yet, simplify this whole + // notion of parameter copying above. return 0; } @@ -154,32 +150,17 @@ int EVP_PKEY_bits(const EVP_PKEY *pkey) { return 0; } -int EVP_PKEY_id(const EVP_PKEY *pkey) { return pkey->type; } - -// evp_pkey_asn1_find returns the ASN.1 method table for the given |nid|, which -// should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is -// unknown. -static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) { - switch (nid) { - case EVP_PKEY_RSA: - return &rsa_asn1_meth; - case EVP_PKEY_EC: - return &ec_asn1_meth; - case EVP_PKEY_DSA: - return &dsa_asn1_meth; - case EVP_PKEY_ED25519: - return &ed25519_asn1_meth; - case EVP_PKEY_X25519: - return &x25519_asn1_meth; - default: - return NULL; - } +int EVP_PKEY_id(const EVP_PKEY *pkey) { + return pkey->ameth != nullptr ? pkey->ameth->pkey_id : EVP_PKEY_NONE; } -void evp_pkey_set_method(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method) { - free_it(pkey); +void evp_pkey_set0(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method, + void *pkey_data) { + if (pkey->ameth && pkey->ameth->pkey_free) { + pkey->ameth->pkey_free(pkey); + } pkey->ameth = method; - pkey->type = pkey->ameth->pkey_id; + pkey->pkey = pkey_data; } int EVP_PKEY_type(int nid) { @@ -210,84 +191,85 @@ int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) { if (pkey && pkey->pkey) { - // This isn't strictly necessary, but historically |EVP_PKEY_set_type| would - // clear |pkey| even if |evp_pkey_asn1_find| failed, so we preserve that - // behavior. - free_it(pkey); + // Some callers rely on |pkey| getting cleared even if |type| is + // unsupported, usually setting |type| to |EVP_PKEY_NONE|. + evp_pkey_set0(pkey, nullptr, nullptr); } - const EVP_PKEY_ASN1_METHOD *ameth = evp_pkey_asn1_find(type); - if (ameth == NULL) { + // This function broadly isn't useful. It initializes |EVP_PKEY| for a type, + // but forgets to put anything in the |pkey|. The one pattern where it does + // anything is |EVP_PKEY_X25519|, where it's needed to make + // |EVP_PKEY_set1_tls_encodedpoint| work, so we support only that. + const EVP_PKEY_ASN1_METHOD *ameth; + if (type == EVP_PKEY_X25519) { + ameth = &x25519_asn1_meth; + } else { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); ERR_add_error_dataf("algorithm %d", type); return 0; } if (pkey) { - evp_pkey_set_method(pkey, ameth); + evp_pkey_set0(pkey, ameth, nullptr); } return 1; } +EVP_PKEY *EVP_PKEY_from_raw_private_key(const EVP_PKEY_ALG *alg, + const uint8_t *in, size_t len) { + if (alg->method->set_priv_raw == nullptr) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return nullptr; + } + bssl::UniquePtr ret(EVP_PKEY_new()); + if (ret == nullptr || !alg->method->set_priv_raw(ret.get(), in, len)) { + return nullptr; + } + return ret.release(); +} + +EVP_PKEY *EVP_PKEY_from_raw_public_key(const EVP_PKEY_ALG *alg, + const uint8_t *in, size_t len) { + if (alg->method->set_pub_raw == nullptr) { + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return nullptr; + } + bssl::UniquePtr ret(EVP_PKEY_new()); + if (ret == nullptr || !alg->method->set_pub_raw(ret.get(), in, len)) { + return nullptr; + } + return ret.release(); +} + EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *unused, const uint8_t *in, size_t len) { // To avoid pulling in all key types, look for specifically the key types that // support |set_priv_raw|. - const EVP_PKEY_ASN1_METHOD *method; switch (type) { case EVP_PKEY_X25519: - method = &x25519_asn1_meth; - break; + return EVP_PKEY_from_raw_private_key(EVP_pkey_x25519(), in, len); case EVP_PKEY_ED25519: - method = &ed25519_asn1_meth; - break; + return EVP_PKEY_from_raw_private_key(EVP_pkey_ed25519(), in, len); default: OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); return nullptr; } - - bssl::UniquePtr ret(EVP_PKEY_new()); - if (ret == nullptr) { - return nullptr; - } - evp_pkey_set_method(ret.get(), method); - - if (!ret->ameth->set_priv_raw(ret.get(), in, len)) { - return nullptr; - } - - return ret.release(); } EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *unused, const uint8_t *in, size_t len) { // To avoid pulling in all key types, look for specifically the key types that // support |set_pub_raw|. - const EVP_PKEY_ASN1_METHOD *method; switch (type) { case EVP_PKEY_X25519: - method = &x25519_asn1_meth; - break; + return EVP_PKEY_from_raw_public_key(EVP_pkey_x25519(), in, len); case EVP_PKEY_ED25519: - method = &ed25519_asn1_meth; - break; + return EVP_PKEY_from_raw_public_key(EVP_pkey_ed25519(), in, len); default: OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); return nullptr; } - - bssl::UniquePtr ret(EVP_PKEY_new()); - if (ret == nullptr) { - return nullptr; - } - evp_pkey_set_method(ret.get(), method); - - if (!ret->ameth->set_pub_raw(ret.get(), in, len)) { - return nullptr; - } - - return ret.release(); } int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, uint8_t *out, @@ -311,7 +293,7 @@ int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, uint8_t *out, } int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { - if (a->type != b->type) { + if (EVP_PKEY_id(a) != EVP_PKEY_id(b)) { return -1; } if (a->ameth && a->ameth->param_cmp) { diff --git a/Sources/CCryptoBoringSSL/crypto/evp/evp_asn1.cc b/Sources/CCryptoBoringSSL/crypto/evp/evp_asn1.cc index 6740d4a2b..26c4b29dd 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/evp_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/evp_asn1.cc @@ -16,84 +16,68 @@ #include +#include + #include #include #include #include #include +#include #include "internal.h" #include "../bytestring/internal.h" #include "../internal.h" -// We intentionally omit |dh_asn1_meth| from this list. It is not serializable. -static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = { - &rsa_asn1_meth, - &ec_asn1_meth, - &dsa_asn1_meth, - &ed25519_asn1_meth, - &x25519_asn1_meth, -}; - -static const EVP_PKEY_ASN1_METHOD *parse_key_type(CBS *cbs) { - CBS oid; - if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) { - return NULL; - } - - for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) { - const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i]; - if (CBS_len(&oid) == method->oid_len && - OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) { - return method; - } - } - - return NULL; -} - -EVP_PKEY *EVP_parse_public_key(CBS *cbs) { +EVP_PKEY *EVP_PKEY_from_subject_public_key_info(const uint8_t *in, size_t len, + const EVP_PKEY_ALG *const *algs, + size_t num_algs) { // Parse the SubjectPublicKeyInfo. - CBS spki, algorithm, key; - uint8_t padding; - if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) || + CBS cbs, spki, algorithm, oid, key; + CBS_init(&cbs, in, len); + if (!CBS_get_asn1(&cbs, &spki, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) || - CBS_len(&spki) != 0) { - OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return nullptr; - } - const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm); - if (method == nullptr) { - OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); - return nullptr; - } - if (// Every key type defined encodes the key as a byte string with the same - // conversion to BIT STRING. - !CBS_get_u8(&key, &padding) || - padding != 0) { + CBS_len(&spki) != 0 || // + CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return nullptr; } - // Set up an |EVP_PKEY| of the appropriate type. bssl::UniquePtr ret(EVP_PKEY_new()); if (ret == nullptr) { return nullptr; } - evp_pkey_set_method(ret.get(), method); - - // Call into the type-specific SPKI decoding function. - if (ret->ameth->pub_decode == nullptr) { - OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); - return nullptr; - } - if (!ret->ameth->pub_decode(ret.get(), &algorithm, &key)) { - return nullptr; + for (const EVP_PKEY_ALG *alg : bssl::Span(algs, num_algs)) { + if (alg->method->pub_decode == nullptr || + bssl::Span(alg->method->oid, alg->method->oid_len) != oid) { + continue; + } + // Every key type we support encodes the key as a byte string with the same + // conversion to BIT STRING, so perform that common conversion ahead of + // time, but only after the OID is recognized as supported. + CBS key_bytes = key; + uint8_t padding; + if (!CBS_get_u8(&key_bytes, &padding) || padding != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return nullptr; + } + CBS params = algorithm; + switch (alg->method->pub_decode(alg, ret.get(), ¶ms, &key_bytes)) { + case evp_decode_error: + return nullptr; + case evp_decode_ok: + return ret.release(); + case evp_decode_unsupported: + // Continue trying other algorithms. + break; + } } - return ret.release(); + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return nullptr; } int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) { @@ -105,43 +89,47 @@ int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) { return key->ameth->pub_encode(cbb, key); } -EVP_PKEY *EVP_parse_private_key(CBS *cbs) { +EVP_PKEY *EVP_PKEY_from_private_key_info(const uint8_t *in, size_t len, + const EVP_PKEY_ALG *const *algs, + size_t num_algs) { // Parse the PrivateKeyInfo. - CBS pkcs8, algorithm, key; + CBS cbs, pkcs8, oid, algorithm, key; uint64_t version; - if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) || - !CBS_get_asn1_uint64(&pkcs8, &version) || - version != 0 || + CBS_init(&cbs, in, len); + if (!CBS_get_asn1(&cbs, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&pkcs8, &version) || version != 0 || !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || - !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) { + !CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || + !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING) || + // A PrivateKeyInfo ends with a SET of Attributes which we ignore. + CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return nullptr; } - const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm); - if (method == nullptr) { - OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); - return nullptr; - } - - // A PrivateKeyInfo ends with a SET of Attributes which we ignore. - // Set up an |EVP_PKEY| of the appropriate type. bssl::UniquePtr ret(EVP_PKEY_new()); if (ret == nullptr) { return nullptr; } - evp_pkey_set_method(ret.get(), method); - - // Call into the type-specific PrivateKeyInfo decoding function. - if (ret->ameth->priv_decode == nullptr) { - OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); - return nullptr; - } - if (!ret->ameth->priv_decode(ret.get(), &algorithm, &key)) { - return nullptr; + for (const EVP_PKEY_ALG *alg : bssl::Span(algs, num_algs)) { + if (alg->method->priv_decode == nullptr || + bssl::Span(alg->method->oid, alg->method->oid_len) != oid) { + continue; + } + CBS params = algorithm, key_copy = key; + switch (alg->method->priv_decode(alg, ret.get(), ¶ms, &key_copy)) { + case evp_decode_error: + return nullptr; + case evp_decode_ok: + return ret.release(); + case evp_decode_unsupported: + // Continue trying other algorithms. + break; + } } - return ret.release(); + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); + return nullptr; } int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) { @@ -153,6 +141,30 @@ int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) { return key->ameth->priv_encode(cbb, key); } +EVP_PKEY *EVP_parse_public_key(CBS *cbs) { + CBS elem; + if (!CBS_get_asn1_element(cbs, &elem, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return nullptr; + } + + auto algs = bssl::GetDefaultEVPAlgorithms(); + return EVP_PKEY_from_subject_public_key_info(CBS_data(&elem), CBS_len(&elem), + algs.data(), algs.size()); +} + +EVP_PKEY *EVP_parse_private_key(CBS *cbs) { + CBS elem; + if (!CBS_get_asn1_element(cbs, &elem, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return nullptr; + } + + auto algs = bssl::GetDefaultEVPAlgorithms(); + return EVP_PKEY_from_private_key_info(CBS_data(&elem), CBS_len(&elem), + algs.data(), algs.size()); +} + static bssl::UniquePtr old_priv_decode(CBS *cbs, int type) { bssl::UniquePtr ret(EVP_PKEY_new()); if (ret == nullptr) { @@ -192,35 +204,26 @@ static bssl::UniquePtr old_priv_decode(CBS *cbs, int type) { EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp, long len) { - if (len < 0) { - OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return nullptr; - } - - // Parse with the legacy format. - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - bssl::UniquePtr ret = old_priv_decode(&cbs, type); - if (ret == nullptr) { - // Try again with PKCS#8. - ERR_clear_error(); - CBS_init(&cbs, *inp, (size_t)len); - ret.reset(EVP_parse_private_key(&cbs)); - if (ret == nullptr) { - return nullptr; - } - if (ret->type != type) { - OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); - return nullptr; - } - } - - if (out != nullptr) { - EVP_PKEY_free(*out); - *out = ret.get(); - } - *inp = CBS_data(&cbs); - return ret.release(); + return bssl::D2IFromCBS( + out, inp, len, [&](CBS *cbs) -> bssl::UniquePtr { + // Parse with the legacy format. + CBS copy = *cbs; + bssl::UniquePtr ret = old_priv_decode(cbs, type); + if (ret == nullptr) { + // Try again with PKCS#8. + ERR_clear_error(); + *cbs = copy; + ret.reset(EVP_parse_private_key(cbs)); + if (ret == nullptr) { + return nullptr; + } + if (EVP_PKEY_id(ret.get()) != type) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); + return nullptr; + } + } + return ret; + }); } // num_elements parses one SEQUENCE from |in| and returns the number of elements @@ -279,7 +282,7 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) { } int i2d_PublicKey(const EVP_PKEY *key, uint8_t **outp) { - switch (key->type) { + switch (EVP_PKEY_id(key)) { case EVP_PKEY_RSA: return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(key), outp); case EVP_PKEY_DSA: @@ -294,93 +297,70 @@ int i2d_PublicKey(const EVP_PKEY *key, uint8_t **outp) { EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out, const uint8_t **inp, long len) { - bssl::UniquePtr ret(EVP_PKEY_new()); - if (ret == nullptr) { - return nullptr; - } - - CBS cbs; - CBS_init(&cbs, *inp, len < 0 ? 0 : (size_t)len); - switch (type) { - case EVP_PKEY_RSA: { - bssl::UniquePtr rsa(RSA_parse_public_key(&cbs)); - if (rsa == nullptr) { - return nullptr; - } - EVP_PKEY_assign_RSA(ret.get(), rsa.release()); - break; - } - - // Unlike OpenSSL, we do not support EC keys with this API. The raw EC - // public key serialization requires knowing the group. In OpenSSL, calling - // this function with |EVP_PKEY_EC| and setting |out| to nullptr does not - // work. It requires |*out| to include a partially-initialized |EVP_PKEY| to - // extract the group. - default: - OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE); - return nullptr; - } - - *inp = CBS_data(&cbs); - if (out != nullptr) { - EVP_PKEY_free(*out); - *out = ret.get(); - } - return ret.release(); + return bssl::D2IFromCBS( + out, inp, len, [&](CBS *cbs) -> bssl::UniquePtr { + bssl::UniquePtr ret(EVP_PKEY_new()); + if (ret == nullptr) { + return nullptr; + } + switch (type) { + case EVP_PKEY_RSA: { + bssl::UniquePtr rsa(RSA_parse_public_key(cbs)); + if (rsa == nullptr) { + return nullptr; + } + EVP_PKEY_assign_RSA(ret.get(), rsa.release()); + return ret; + } + + // Unlike OpenSSL, we do not support EC keys with this API. The raw EC + // public key serialization requires knowing the group. In OpenSSL, + // calling this function with |EVP_PKEY_EC| and setting |out| to + // nullptr does not work. It requires |*out| to include a + // partially-initialized |EVP_PKEY| to extract the group. + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return nullptr; + } + }); } EVP_PKEY *d2i_PUBKEY(EVP_PKEY **out, const uint8_t **inp, long len) { - if (len < 0) { - return nullptr; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - bssl::UniquePtr ret(EVP_parse_public_key(&cbs)); - if (ret == nullptr) { - return nullptr; - } - if (out != nullptr) { - EVP_PKEY_free(*out); - *out = ret.get(); - } - *inp = CBS_data(&cbs); - return ret.release(); + return bssl::D2IFromCBS(out, inp, len, EVP_parse_public_key); } int i2d_PUBKEY(const EVP_PKEY *pkey, uint8_t **outp) { - if (pkey == NULL) { + if (pkey == nullptr) { return 0; } + return bssl::I2DFromCBB( + /*initial_capacity=*/128, outp, + [&](CBB *cbb) -> bool { return EVP_marshal_public_key(cbb, pkey); }); +} - CBB cbb; - if (!CBB_init(&cbb, 128) || - !EVP_marshal_public_key(&cbb, pkey)) { - CBB_cleanup(&cbb); - return -1; +static bssl::UniquePtr parse_spki( + CBS *cbs, bssl::Span algs) { + CBS spki; + if (!CBS_get_asn1_element(cbs, &spki, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return nullptr; } - return CBB_finish_i2d(&cbb, outp); + return bssl::UniquePtr(EVP_PKEY_from_subject_public_key_info( + CBS_data(&spki), CBS_len(&spki), algs.data(), algs.size())); +} + +static bssl::UniquePtr parse_spki(CBS *cbs, const EVP_PKEY_ALG *alg) { + return parse_spki(cbs, bssl::Span(&alg, 1)); } RSA *d2i_RSA_PUBKEY(RSA **out, const uint8_t **inp, long len) { - if (len < 0) { - return nullptr; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - bssl::UniquePtr pkey(EVP_parse_public_key(&cbs)); - if (pkey == nullptr) { - return nullptr; - } - bssl::UniquePtr rsa(EVP_PKEY_get1_RSA(pkey.get())); - if (rsa == nullptr) { - return nullptr; - } - if (out != nullptr) { - RSA_free(*out); - *out = rsa.get(); - } - *inp = CBS_data(&cbs); - return rsa.release(); + return bssl::D2IFromCBS(out, inp, len, [](CBS *cbs) -> bssl::UniquePtr { + bssl::UniquePtr pkey = parse_spki(cbs, EVP_pkey_rsa()); + if (pkey == nullptr) { + return nullptr; + } + return bssl::UniquePtr(EVP_PKEY_get1_RSA(pkey.get())); + }); } int i2d_RSA_PUBKEY(const RSA *rsa, uint8_t **outp) { @@ -398,25 +378,13 @@ int i2d_RSA_PUBKEY(const RSA *rsa, uint8_t **outp) { } DSA *d2i_DSA_PUBKEY(DSA **out, const uint8_t **inp, long len) { - if (len < 0) { - return nullptr; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - bssl::UniquePtr pkey(EVP_parse_public_key(&cbs)); - if (pkey == nullptr) { - return nullptr; - } - bssl::UniquePtr dsa(EVP_PKEY_get1_DSA(pkey.get())); - if (dsa == nullptr) { - return nullptr; - } - if (out != nullptr) { - DSA_free(*out); - *out = dsa.get(); - } - *inp = CBS_data(&cbs); - return dsa.release(); + return bssl::D2IFromCBS(out, inp, len, [](CBS *cbs) -> bssl::UniquePtr { + bssl::UniquePtr pkey = parse_spki(cbs, EVP_pkey_dsa()); + if (pkey == nullptr) { + return nullptr; + } + return bssl::UniquePtr(EVP_PKEY_get1_DSA(pkey.get())); + }); } int i2d_DSA_PUBKEY(const DSA *dsa, uint8_t **outp) { @@ -434,25 +402,17 @@ int i2d_DSA_PUBKEY(const DSA *dsa, uint8_t **outp) { } EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp, long len) { - if (len < 0) { - return nullptr; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - bssl::UniquePtr pkey(EVP_parse_public_key(&cbs)); - if (pkey == nullptr) { - return nullptr; - } - bssl::UniquePtr ec_key(EVP_PKEY_get1_EC_KEY(pkey.get())); - if (ec_key == nullptr) { - return nullptr; - } - if (out != nullptr) { - EC_KEY_free(*out); - *out = ec_key.get(); - } - *inp = CBS_data(&cbs); - return ec_key.release(); + return bssl::D2IFromCBS( + out, inp, len, [](CBS *cbs) -> bssl::UniquePtr { + const EVP_PKEY_ALG *const algs[] = { + EVP_pkey_ec_p224(), EVP_pkey_ec_p256(), EVP_pkey_ec_p384(), + EVP_pkey_ec_p521()}; + bssl::UniquePtr pkey = parse_spki(cbs, algs); + if (pkey == nullptr) { + return nullptr; + } + return bssl::UniquePtr(EVP_PKEY_get1_EC_KEY(pkey.get())); + }); } int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp) { diff --git a/Sources/CCryptoBoringSSL/crypto/evp/evp_ctx.cc b/Sources/CCryptoBoringSSL/crypto/evp/evp_ctx.cc index ebf9034f6..f9ff9b94c 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/evp_ctx.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/evp_ctx.cc @@ -25,29 +25,31 @@ #include "internal.h" -static const EVP_PKEY_METHOD *const evp_methods[] = { +// |EVP_PKEY_RSA_PSS| is intentionally omitted from this list. These are types +// that can be created without an |EVP_PKEY|, and we do not support +// |EVP_PKEY_RSA_PSS| keygen. +static const EVP_PKEY_CTX_METHOD *const evp_methods[] = { &rsa_pkey_meth, &ec_pkey_meth, &ed25519_pkey_meth, &x25519_pkey_meth, &hkdf_pkey_meth, }; -static const EVP_PKEY_METHOD *evp_pkey_meth_find(int type) { - for (size_t i = 0; i < sizeof(evp_methods) / sizeof(EVP_PKEY_METHOD *); i++) { - if (evp_methods[i]->pkey_id == type) { - return evp_methods[i]; +static const EVP_PKEY_CTX_METHOD *evp_pkey_meth_find(int type) { + for (auto method : evp_methods) { + if (method->pkey_id == type) { + return method; } } - return NULL; + return nullptr; } -static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, - const EVP_PKEY_METHOD *pmeth) { +static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, + const EVP_PKEY_CTX_METHOD *pmeth) { bssl::UniquePtr ret = bssl::MakeUnique(); if (!ret) { return nullptr; } - ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; ret->pkey = bssl::UpRef(pkey); @@ -66,25 +68,25 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) { return NULL; } - const EVP_PKEY_METHOD *pkey_method = pkey->ameth->pkey_method; + const EVP_PKEY_CTX_METHOD *pkey_method = pkey->ameth->pkey_method; if (pkey_method == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); ERR_add_error_dataf("algorithm %d", pkey->ameth->pkey_id); return NULL; } - return evp_pkey_ctx_new(pkey, e, pkey_method); + return evp_pkey_ctx_new(pkey, pkey_method); } EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) { - const EVP_PKEY_METHOD *pkey_method = evp_pkey_meth_find(id); + const EVP_PKEY_CTX_METHOD *pkey_method = evp_pkey_meth_find(id); if (pkey_method == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM); ERR_add_error_dataf("algorithm %d", id); return NULL; } - return evp_pkey_ctx_new(NULL, e, pkey_method); + return evp_pkey_ctx_new(NULL, pkey_method); } evp_pkey_ctx_st::~evp_pkey_ctx_st() { @@ -106,7 +108,6 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx) { } ret->pmeth = ctx->pmeth; - ret->engine = ctx->engine; ret->operation = ctx->operation; ret->pkey = bssl::UpRef(ctx->pkey); ret->peerkey = bssl::UpRef(ctx->peerkey); @@ -297,7 +298,7 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) { return 0; } - if (ctx->pkey->type != peer->type) { + if (EVP_PKEY_id(ctx->pkey.get()) != EVP_PKEY_id(peer)) { OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); return 0; } diff --git a/Sources/CCryptoBoringSSL/crypto/evp/internal.h b/Sources/CCryptoBoringSSL/crypto/evp/internal.h index 913fe3888..baf4c29a0 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/evp/internal.h @@ -15,9 +15,11 @@ #ifndef OPENSSL_HEADER_CRYPTO_EVP_INTERNAL_H #define OPENSSL_HEADER_CRYPTO_EVP_INTERNAL_H -#include +#include -#include +#include + +#include #include "../internal.h" @@ -27,23 +29,46 @@ extern "C" { typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; -typedef struct evp_pkey_method_st EVP_PKEY_METHOD; +typedef struct evp_pkey_ctx_method_st EVP_PKEY_CTX_METHOD; + +struct evp_pkey_alg_st { + // method implements operations for this |EVP_PKEY_ALG|. + const EVP_PKEY_ASN1_METHOD *method; + + // ec_group returns the |EC_GROUP| for this algorithm, if |method| is for + // |EVP_PKEY_EC|. + const EC_GROUP *(*ec_group)(); +}; + +enum evp_decode_result_t { + evp_decode_error = 0, + evp_decode_ok = 1, + evp_decode_unsupported = 2, +}; struct evp_pkey_asn1_method_st { + // pkey_id contains one of the |EVP_PKEY_*| values and corresponds to the OID + // in the key type's AlgorithmIdentifier. int pkey_id; uint8_t oid[9]; uint8_t oid_len; - const EVP_PKEY_METHOD *pkey_method; + const EVP_PKEY_CTX_METHOD *pkey_method; // pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo - // and writes the result into |out|. It returns one on success and zero on - // error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER - // type field, and |key| is the contents of the subjectPublicKey with the - // leading padding byte checked and removed. Although X.509 uses BIT STRINGs - // to represent SubjectPublicKeyInfo, every key type defined encodes the key - // as a byte string with the same conversion to BIT STRING. - int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key); + // and writes the result into |out|. It returns |evp_decode_ok| on success, + // and |evp_decode_error| on error, and |evp_decode_unsupported| if the input + // was not supported by this |EVP_PKEY_ALG|. In case of + // |evp_decode_unsupported|, it does not add an error to the error queue. May + // modify |params| and |key|. Callers must make a copy if calling in a loop. + // + // |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, + // and |key| is the contents of the subjectPublicKey with the leading padding + // byte checked and removed. Although X.509 uses BIT STRINGs to represent + // SubjectPublicKeyInfo, every key type defined encodes the key as a byte + // string with the same conversion to BIT STRING. + evp_decode_result_t (*pub_decode)(const EVP_PKEY_ALG *alg, EVP_PKEY *out, + CBS *params, CBS *key); // pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result // to |out|. It returns one on success and zero on error. @@ -52,10 +77,16 @@ struct evp_pkey_asn1_method_st { int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b); // priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the - // result into |out|. It returns one on success and zero on error. |params| is - // the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key| - // is the contents of the OCTET STRING privateKey field. - int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key); + // result into |out|. It returns |evp_decode_ok| on success, and + // |evp_decode_error| on error, and |evp_decode_unsupported| if the key type + // was not supported by this |EVP_PKEY_ALG|. In case of + // |evp_decode_unsupported|, it does not add an error to the error queue. May + // modify |params| and |key|. Callers must make a copy if calling in a loop. + // + // |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, + // and |key| is the contents of the OCTET STRING privateKey field. + evp_decode_result_t (*priv_decode)(const EVP_PKEY_ALG *alg, EVP_PKEY *out, + CBS *params, CBS *key); // priv_encode encodes |key| as a PrivateKeyInfo and appends the result to // |out|. It returns one on success and zero on error. @@ -94,15 +125,11 @@ struct evp_pkey_asn1_method_st { struct evp_pkey_st { CRYPTO_refcount_t references; - // type contains one of the EVP_PKEY_* values or NID_undef and determines - // the type of |pkey|. - int type; - - // pkey contains a pointer to a structure dependent on |type|. + // pkey contains a pointer to a structure dependent on |ameth|. void *pkey; - // ameth contains a pointer to a method table that contains many ASN.1 - // methods for the key type. + // ameth contains a pointer to a method table that determines the key type, or + // nullptr if the key is empty. const EVP_PKEY_ASN1_METHOD *ameth; } /* EVP_PKEY */; @@ -167,7 +194,7 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, #define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 10) #define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11) #define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12) -#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 13) +#define EVP_PKEY_CTRL_EC_PARAMGEN_GROUP (EVP_PKEY_ALG_CTRL + 13) #define EVP_PKEY_CTRL_HKDF_MODE (EVP_PKEY_ALG_CTRL + 14) #define EVP_PKEY_CTRL_HKDF_MD (EVP_PKEY_ALG_CTRL + 15) #define EVP_PKEY_CTRL_HKDF_KEY (EVP_PKEY_ALG_CTRL + 16) @@ -179,20 +206,21 @@ struct evp_pkey_ctx_st { ~evp_pkey_ctx_st(); // Method associated with this operation - const EVP_PKEY_METHOD *pmeth = nullptr; - // Engine that implements this method or nullptr if builtin - ENGINE *engine = nullptr; + const EVP_PKEY_CTX_METHOD *pmeth = nullptr; // Key: may be nullptr bssl::UniquePtr pkey; // Peer key for key agreement, may be nullptr bssl::UniquePtr peerkey; // operation contains one of the |EVP_PKEY_OP_*| values. int operation = EVP_PKEY_OP_UNDEFINED; - // Algorithm specific data + // Algorithm specific data. + // TODO(davidben): Since a |EVP_PKEY_CTX| never has its type change after + // creation, this should instead be a base class, with the algorithm-specific + // data on the subclass, coming from the same allocation. void *data = nullptr; } /* EVP_PKEY_CTX */; -struct evp_pkey_method_st { +struct evp_pkey_ctx_method_st { int pkey_id; int (*init)(EVP_PKEY_CTX *ctx); @@ -227,7 +255,7 @@ struct evp_pkey_method_st { int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2); -} /* EVP_PKEY_METHOD */; +} /* EVP_PKEY_CTX_METHOD */; typedef struct { // key is the concatenation of the private seed and public key. It is stored @@ -249,24 +277,47 @@ typedef struct { extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth; extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth; extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth; +extern const EVP_PKEY_ASN1_METHOD rsa_pss_sha256_asn1_meth; extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth; extern const EVP_PKEY_ASN1_METHOD x25519_asn1_meth; extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth; -extern const EVP_PKEY_METHOD rsa_pkey_meth; -extern const EVP_PKEY_METHOD ec_pkey_meth; -extern const EVP_PKEY_METHOD ed25519_pkey_meth; -extern const EVP_PKEY_METHOD x25519_pkey_meth; -extern const EVP_PKEY_METHOD hkdf_pkey_meth; -extern const EVP_PKEY_METHOD dh_pkey_meth; +extern const EVP_PKEY_CTX_METHOD rsa_pkey_meth; +extern const EVP_PKEY_CTX_METHOD rsa_pss_sha256_pkey_meth; +extern const EVP_PKEY_CTX_METHOD ec_pkey_meth; +extern const EVP_PKEY_CTX_METHOD ed25519_pkey_meth; +extern const EVP_PKEY_CTX_METHOD x25519_pkey_meth; +extern const EVP_PKEY_CTX_METHOD hkdf_pkey_meth; +extern const EVP_PKEY_CTX_METHOD dh_pkey_meth; -// evp_pkey_set_method behaves like |EVP_PKEY_set_type|, but takes a pointer to -// a method table. This avoids depending on every |EVP_PKEY_ASN1_METHOD|. -void evp_pkey_set_method(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method); +// evp_pkey_set0 sets |pkey|'s method to |method| and data to |pkey_data|, +// freeing any key that may previously have been configured. This function takes +// ownership of |pkey_data|, which must be of the type expected by |method|. +void evp_pkey_set0(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method, + void *pkey_data); #if defined(__cplusplus) } // extern C #endif +BSSL_NAMESPACE_BEGIN +inline auto GetDefaultEVPAlgorithms() { + // A set of algorithms to use by default in |EVP_parse_public_key| and + // |EVP_parse_private_key|. + return std::array{ + EVP_pkey_ec_p224(), + EVP_pkey_ec_p256(), + EVP_pkey_ec_p384(), + EVP_pkey_ec_p521(), + EVP_pkey_ed25519(), + EVP_pkey_rsa(), + EVP_pkey_x25519(), + // TODO(crbug.com/438761503): Remove DSA from this set, after callers that + // need DSA pass in |EVP_pkey_dsa| explicitly. + EVP_pkey_dsa(), + }; +} +BSSL_NAMESPACE_END + #endif // OPENSSL_HEADER_CRYPTO_EVP_INTERNAL_H diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_dh.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_dh.cc index dcf4e7c81..b70d92fd6 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_dh.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_dh.cc @@ -129,7 +129,7 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } } -const EVP_PKEY_METHOD dh_pkey_meth = { +const EVP_PKEY_CTX_METHOD dh_pkey_meth = { /*pkey_id=*/EVP_PKEY_DH, /*init=*/pkey_dh_init, /*copy=*/pkey_dh_copy, diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_dh_asn1.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_dh_asn1.cc index f600f43c6..55fbca3e9 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_dh_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_dh_asn1.cc @@ -120,13 +120,15 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) { } int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) { - evp_pkey_set_method(pkey, &dh_asn1_meth); - pkey->pkey = key; - return key != NULL; + if (key == nullptr) { + return 0; + } + evp_pkey_set0(pkey, &dh_asn1_meth, key); + return 1; } DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey) { - if (pkey->type != EVP_PKEY_DH) { + if (EVP_PKEY_id(pkey) != EVP_PKEY_DH) { OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DH_KEY); return NULL; } diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_dsa_asn1.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_dsa_asn1.cc index c8e40ad97..c4df801d4 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_dsa_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_dsa_asn1.cc @@ -24,36 +24,32 @@ #include "internal.h" -static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t dsa_pub_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 3279, section 2.3.2. - // Parameters may or may not be present. - bssl::UniquePtr dsa; - if (CBS_len(params) == 0) { - dsa.reset(DSA_new()); - if (dsa == nullptr) { - return 0; - } - } else { - dsa.reset(DSA_parse_parameters(params)); - if (dsa == nullptr || CBS_len(params) != 0) { - OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; - } + // Decode parameters. RFC 3279 permits DSA parameters to be omitted, in which + // case they are implicitly determined from the issuing certificate, or + // somewhere unspecified and out-of-band. We do not support this mode. + bssl::UniquePtr dsa(DSA_parse_parameters(params)); + if (dsa == nullptr || CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return evp_decode_error; } dsa->pub_key = BN_new(); if (dsa->pub_key == nullptr) { - return 0; + return evp_decode_error; } if (!BN_parse_asn1_unsigned(key, dsa->pub_key) || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } EVP_PKEY_assign_DSA(out, dsa.release()); - return 1; + return evp_decode_ok; } static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) { @@ -78,23 +74,25 @@ static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t dsa_priv_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See PKCS#11, v2.40, section 2.5. // Decode parameters. bssl::UniquePtr dsa(DSA_parse_parameters(params)); if (dsa == nullptr || CBS_len(params) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } dsa->priv_key = BN_new(); if (dsa->priv_key == nullptr) { - return 0; + return evp_decode_error; } if (!BN_parse_asn1_unsigned(key, dsa->priv_key) || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } // To avoid DoS attacks when importing private keys, check bounds on |dsa|. @@ -102,7 +100,7 @@ static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { // width. if (!dsa_check_key(dsa.get())) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } // Calculate the public key. @@ -111,11 +109,11 @@ static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { if (ctx == nullptr || dsa->pub_key == nullptr || !BN_mod_exp_mont_consttime(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx.get(), nullptr)) { - return 0; + return evp_decode_error; } EVP_PKEY_assign_DSA(out, dsa.release()); - return 1; + return evp_decode_ok; } static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) { @@ -236,6 +234,14 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = { int_dsa_free, }; +const EVP_PKEY_ALG *EVP_pkey_dsa(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&dsa_asn1_meth, + /*ec_group=*/nullptr, + }; + return &kAlg; +} + int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits) { // BoringSSL does not support DSA in |EVP_PKEY_CTX|. OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); @@ -257,13 +263,15 @@ int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) { } int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) { - evp_pkey_set_method(pkey, &dsa_asn1_meth); - pkey->pkey = key; - return key != nullptr; + if (key == nullptr) { + return 0; + } + evp_pkey_set0(pkey, &dsa_asn1_meth, key); + return 1; } DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey) { - if (pkey->type != EVP_PKEY_DSA) { + if (EVP_PKEY_id(pkey) != EVP_PKEY_DSA) { OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DSA_KEY); return nullptr; } diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_ec.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_ec.cc index a19b97bfb..9bd2396f7 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_ec.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_ec.cc @@ -148,12 +148,8 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { // Default behaviour is OK return 1; - case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: { - const EC_GROUP *group = EC_GROUP_new_by_curve_name(p1); - if (group == NULL) { - return 0; - } - dctx->gen_group = group; + case EVP_PKEY_CTRL_EC_PARAMGEN_GROUP: { + dctx->gen_group = static_cast(p2); return 1; } @@ -197,7 +193,7 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { return 1; } -const EVP_PKEY_METHOD ec_pkey_meth = { +const EVP_PKEY_CTX_METHOD ec_pkey_meth = { EVP_PKEY_EC, pkey_ec_init, pkey_ec_copy, @@ -216,8 +212,13 @@ const EVP_PKEY_METHOD ec_pkey_meth = { }; int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) { + const EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); + if (group == nullptr) { + return 0; + } return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN, - EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL); + EVP_PKEY_CTRL_EC_PARAMGEN_GROUP, 0, + const_cast(group)); } int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int encoding) { diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_ec_asn1.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_ec_asn1.cc index 942769b1b..812d3deba 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_ec_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_ec_asn1.cc @@ -20,7 +20,10 @@ #include #include #include +#include +#include +#include "../ec/internal.h" #include "internal.h" @@ -48,25 +51,35 @@ static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t eckey_pub_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 5480, section 2. - // The parameters are a named curve. - const EC_GROUP *group = EC_KEY_parse_curve_name(params); - if (group == NULL || CBS_len(params) != 0) { + // Check that |params| matches |alg|. Only the namedCurve form is allowed. + const EC_GROUP *group = alg->ec_group(); + if (ec_key_parse_curve_name(params, bssl::Span(&group, 1)) == nullptr) { + if (ERR_equals(ERR_peek_last_error(), ERR_LIB_EC, EC_R_UNKNOWN_GROUP)) { + ERR_clear_error(); + return evp_decode_unsupported; + } OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; + } + if (CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return evp_decode_error; } bssl::UniquePtr eckey(EC_KEY_new()); if (eckey == nullptr || // !EC_KEY_set_group(eckey.get(), group) || !EC_KEY_oct2key(eckey.get(), CBS_data(key), CBS_len(key), nullptr)) { - return 0; + return evp_decode_error; } EVP_PKEY_assign_EC_KEY(out, eckey.release()); - return 1; + return evp_decode_ok; } static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { @@ -85,23 +98,32 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { } } -static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t eckey_priv_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 5915. - const EC_GROUP *group = EC_KEY_parse_parameters(params); - if (group == NULL || CBS_len(params) != 0) { + const EC_GROUP *group = alg->ec_group(); + if (ec_key_parse_parameters(params, bssl::Span(&group, 1)) == nullptr) { + if (ERR_equals(ERR_peek_last_error(), ERR_LIB_EC, EC_R_UNKNOWN_GROUP)) { + ERR_clear_error(); + return evp_decode_unsupported; + } OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; + } + if (CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return evp_decode_error; } - EC_KEY *ec_key = EC_KEY_parse_private_key(key, group); - if (ec_key == NULL || CBS_len(key) != 0) { + bssl::UniquePtr ec_key(ec_key_parse_private_key(key, group, {})); + if (ec_key == nullptr || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - EC_KEY_free(ec_key); - return 0; + return evp_decode_error; } - EVP_PKEY_assign_EC_KEY(out, ec_key); - return 1; + EVP_PKEY_assign_EC_KEY(out, ec_key.release()); + return evp_decode_ok; } static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) { @@ -255,6 +277,39 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = { int_ec_free, }; +const EVP_PKEY_ALG *EVP_pkey_ec_p224(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&ec_asn1_meth, + /*ec_group=*/&EC_group_p224, + }; + return &kAlg; +} + +const EVP_PKEY_ALG *EVP_pkey_ec_p256(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&ec_asn1_meth, + /*ec_group=*/&EC_group_p256, + }; + return &kAlg; +} + +const EVP_PKEY_ALG *EVP_pkey_ec_p384(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&ec_asn1_meth, + /*ec_group=*/&EC_group_p384, + }; + return &kAlg; +} + +const EVP_PKEY_ALG *EVP_pkey_ec_p521(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&ec_asn1_meth, + /*ec_group=*/&EC_group_p521, + }; + return &kAlg; +} + + int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { if (EVP_PKEY_assign_EC_KEY(pkey, key)) { EC_KEY_up_ref(key); @@ -264,14 +319,16 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { } int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { - evp_pkey_set_method(pkey, &ec_asn1_meth); - pkey->pkey = key; - return key != NULL; + if (key == nullptr) { + return 0; + } + evp_pkey_set0(pkey, &ec_asn1_meth, key); + return 1; } EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) { - if (pkey->type != EVP_PKEY_EC) { - OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_EC_KEY_KEY); + if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) { + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_EC_KEY); return NULL; } return reinterpret_cast(pkey->pkey); @@ -284,3 +341,23 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey) { } return ec_key; } + +int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey) { + const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (ec_key == nullptr) { + return NID_undef; + } + const EC_GROUP *group = EC_KEY_get0_group(ec_key); + if (group == nullptr) { + return NID_undef; + } + return EC_GROUP_get_curve_name(group); +} + +int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey) { + const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (ec_key == nullptr) { + return 0; + } + return EC_KEY_get_conv_form(ec_key); +} diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519.cc index a8d19912f..5bfc553a6 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519.cc @@ -31,14 +31,11 @@ static int pkey_ed25519_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { return 0; } - evp_pkey_set_method(pkey, &ed25519_asn1_meth); - uint8_t pubkey_unused[32]; ED25519_keypair(pubkey_unused, key->key); key->has_private = 1; - OPENSSL_free(pkey->pkey); - pkey->pkey = key; + evp_pkey_set0(pkey, &ed25519_asn1_meth, key); return 1; } @@ -84,7 +81,7 @@ static int pkey_ed25519_verify_message(EVP_PKEY_CTX *ctx, const uint8_t *sig, return 1; } -const EVP_PKEY_METHOD ed25519_pkey_meth = { +const EVP_PKEY_CTX_METHOD ed25519_pkey_meth = { /*pkey_id=*/EVP_PKEY_ED25519, /*init=*/nullptr, /*copy=*/pkey_ed25519_copy, diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519_asn1.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519_asn1.cc index 6b2f7b9b2..6625fe68a 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_ed25519_asn1.cc @@ -45,9 +45,7 @@ static int ed25519_set_priv_raw(EVP_PKEY *pkey, const uint8_t *in, size_t len) { uint8_t pubkey_unused[32]; ED25519_keypair_from_seed(pubkey_unused, key->key, in); key->has_private = 1; - - ed25519_free(pkey); - pkey->pkey = key; + evp_pkey_set0(pkey, &ed25519_asn1_meth, key); return 1; } @@ -65,9 +63,7 @@ static int ed25519_set_pub_raw(EVP_PKEY *pkey, const uint8_t *in, size_t len) { OPENSSL_memcpy(key->key + ED25519_PUBLIC_KEY_OFFSET, in, 32); key->has_private = 0; - - ed25519_free(pkey); - pkey->pkey = key; + evp_pkey_set0(pkey, &ed25519_asn1_meth, key); return 1; } @@ -113,16 +109,20 @@ static int ed25519_get_pub_raw(const EVP_PKEY *pkey, uint8_t *out, return 1; } -static int ed25519_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t ed25519_pub_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 8410, section 4. // The parameters must be omitted. Public keys have length 32. if (CBS_len(params) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } - return ed25519_set_pub_raw(out, CBS_data(key), CBS_len(key)); + return ed25519_set_pub_raw(out, CBS_data(key), CBS_len(key)) + ? evp_decode_ok + : evp_decode_error; } static int ed25519_pub_encode(CBB *out, const EVP_PKEY *pkey) { @@ -153,7 +153,9 @@ static int ed25519_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { b_key->key + ED25519_PUBLIC_KEY_OFFSET, 32) == 0; } -static int ed25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t ed25519_priv_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 8410, section 7. // Parameters must be empty. The key is a 32-byte value wrapped in an extra @@ -162,10 +164,12 @@ static int ed25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { if (CBS_len(params) != 0 || !CBS_get_asn1(key, &inner, CBS_ASN1_OCTETSTRING) || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } - return ed25519_set_priv_raw(out, CBS_data(&inner), CBS_len(&inner)); + return ed25519_set_priv_raw(out, CBS_data(&inner), CBS_len(&inner)) + ? evp_decode_ok + : evp_decode_error; } static int ed25519_priv_encode(CBB *out, const EVP_PKEY *pkey) { @@ -223,3 +227,11 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { /*param_cmp=*/NULL, ed25519_free, }; + +const EVP_PKEY_ALG *EVP_pkey_ed25519(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&ed25519_asn1_meth, + /*ec_group=*/nullptr, + }; + return &kAlg; +} diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_hkdf.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_hkdf.cc index 00af6034a..1e917fe7f 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_hkdf.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_hkdf.cc @@ -183,7 +183,7 @@ static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } } -const EVP_PKEY_METHOD hkdf_pkey_meth = { +const EVP_PKEY_CTX_METHOD hkdf_pkey_meth = { /*pkey_id=*/EVP_PKEY_HKDF, pkey_hkdf_init, pkey_hkdf_copy, diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_rsa.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_rsa.cc index a55dd4c8a..0d5912493 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_rsa.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_rsa.cc @@ -24,50 +24,59 @@ #include #include #include +#include #include "../internal.h" +#include "../mem_internal.h" #include "../rsa/internal.h" #include "internal.h" -typedef struct { +namespace { + +struct RSA_PKEY_CTX { // Key gen parameters - int nbits; - BIGNUM *pub_exp; + int nbits = 2048; + bssl::UniquePtr pub_exp; // RSA padding mode - int pad_mode; + int pad_mode = RSA_PKCS1_PADDING; // message digest - const EVP_MD *md; + const EVP_MD *md = nullptr; // message digest for MGF1 - const EVP_MD *mgf1md; + const EVP_MD *mgf1md = nullptr; // PSS salt length - int saltlen; - // tbuf is a buffer which is either NULL, or is the size of the RSA modulus. - // It's used to store the output of RSA operations. - uint8_t *tbuf; - // OAEP label - uint8_t *oaep_label; - size_t oaep_labellen; -} RSA_PKEY_CTX; - -typedef struct { - uint8_t *data; - size_t len; -} RSA_OAEP_LABEL_PARAMS; + int saltlen = RSA_PSS_SALTLEN_DIGEST; + // restrict_pss_params, if true, indicates that the PSS signing/verifying + // parameters are restricted by the key's parameters. |md| and |mgf1md| may + // not change, and |saltlen| must be at least |md|'s hash length. + bool restrict_pss_params = false; + bssl::Array oaep_label; +}; + +static bool is_pss_only(const EVP_PKEY_CTX *ctx) { + return ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS; +} static int pkey_rsa_init(EVP_PKEY_CTX *ctx) { - RSA_PKEY_CTX *rctx = - reinterpret_cast(OPENSSL_zalloc(sizeof(RSA_PKEY_CTX))); + RSA_PKEY_CTX *rctx = bssl::New(); if (!rctx) { return 0; } - rctx->nbits = 2048; - rctx->pad_mode = RSA_PKCS1_PADDING; - rctx->saltlen = -2; + if (is_pss_only(ctx)) { + rctx->pad_mode = RSA_PKCS1_PSS_PADDING; + // Pick up PSS parameters from the key. For now, we only support the SHA-256 + // parameter set, so every key is necessarily SHA-256. If we ever support + // other parameters, we will need more state in |EVP_PKEY| and to translate + // that state into defaults here. + if (ctx->pkey != nullptr) { + rctx->md = rctx->mgf1md = EVP_sha256(); + rctx->saltlen = EVP_MD_size(rctx->md); + rctx->restrict_pss_params = true; + } + } ctx->data = rctx; - return 1; } @@ -80,7 +89,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { dctx = reinterpret_cast(dst->data); dctx->nbits = sctx->nbits; if (sctx->pub_exp) { - dctx->pub_exp = BN_dup(sctx->pub_exp); + dctx->pub_exp.reset(BN_dup(sctx->pub_exp.get())); if (!dctx->pub_exp) { return 0; } @@ -90,42 +99,16 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { dctx->md = sctx->md; dctx->mgf1md = sctx->mgf1md; dctx->saltlen = sctx->saltlen; - if (sctx->oaep_label) { - OPENSSL_free(dctx->oaep_label); - dctx->oaep_label = reinterpret_cast( - OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen)); - if (!dctx->oaep_label) { - return 0; - } - dctx->oaep_labellen = sctx->oaep_labellen; + dctx->restrict_pss_params = sctx->restrict_pss_params; + if (!dctx->oaep_label.CopyFrom(sctx->oaep_label)) { + return 0; } return 1; } static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) { - RSA_PKEY_CTX *rctx = reinterpret_cast(ctx->data); - - if (rctx == NULL) { - return; - } - - BN_free(rctx->pub_exp); - OPENSSL_free(rctx->tbuf); - OPENSSL_free(rctx->oaep_label); - OPENSSL_free(rctx); -} - -static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) { - if (ctx->tbuf) { - return 1; - } - ctx->tbuf = reinterpret_cast( - OPENSSL_malloc(EVP_PKEY_size(pk->pkey.get()))); - if (!ctx->tbuf) { - return 0; - } - return 1; + bssl::Delete(reinterpret_cast(ctx->data)); } static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, @@ -187,12 +170,13 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, size_t rslen; const size_t key_len = EVP_PKEY_size(ctx->pkey.get()); - if (!setup_tbuf(rctx, ctx) || - !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen, + bssl::Array tbuf; + if (!tbuf.InitForOverwrite(key_len) || + !RSA_verify_raw(rsa, &rslen, tbuf.data(), tbuf.size(), sig, siglen, rctx->pad_mode)) { return 0; } - if (rslen != tbslen || CRYPTO_memcmp(tbs, rctx->tbuf, rslen) != 0) { + if (rslen != tbslen || CRYPTO_memcmp(tbs, tbuf.data(), rslen) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE); return 0; } @@ -232,33 +216,28 @@ static int pkey_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, uint8_t *asn1_prefix; size_t asn1_prefix_len; int asn1_prefix_allocated; - if (!setup_tbuf(rctx, ctx) || - !RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len, + if (!RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len, &asn1_prefix_allocated, EVP_MD_type(rctx->md), kDummyHash, hash_len)) { return 0; } + bssl::UniquePtr free_asn1_prefix(asn1_prefix_allocated ? asn1_prefix + : nullptr); + bssl::Array tbuf; size_t rslen; - int ok = 1; - if (!RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, sig_len, + if (!tbuf.InitForOverwrite(key_len) || + !RSA_verify_raw(rsa, &rslen, tbuf.data(), tbuf.size(), sig, sig_len, RSA_PKCS1_PADDING) || rslen != asn1_prefix_len || // Compare all but the hash suffix. - CRYPTO_memcmp(rctx->tbuf, asn1_prefix, asn1_prefix_len - hash_len) != 0) { - ok = 0; - } - - if (asn1_prefix_allocated) { - OPENSSL_free(asn1_prefix); - } - - if (!ok) { + CRYPTO_memcmp(tbuf.data(), asn1_prefix, asn1_prefix_len - hash_len) != + 0) { return 0; } if (out != NULL) { - OPENSSL_memcpy(out, rctx->tbuf + rslen - hash_len, hash_len); + OPENSSL_memcpy(out, tbuf.data() + rslen - hash_len, hash_len); } *out_len = hash_len; @@ -282,11 +261,12 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, } if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { - if (!setup_tbuf(rctx, ctx) || - !RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, key_len, in, inlen, - rctx->oaep_label, rctx->oaep_labellen, - rctx->md, rctx->mgf1md) || - !RSA_encrypt(rsa, outlen, out, *outlen, rctx->tbuf, key_len, + bssl::Array tbuf; + if (!tbuf.InitForOverwrite(key_len) || + !RSA_padding_add_PKCS1_OAEP_mgf1( + tbuf.data(), tbuf.size(), in, inlen, rctx->oaep_label.data(), + rctx->oaep_label.size(), rctx->md, rctx->mgf1md) || + !RSA_encrypt(rsa, outlen, out, *outlen, tbuf.data(), tbuf.size(), RSA_NO_PADDING)) { return 0; } @@ -313,13 +293,15 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen, } if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) { + bssl::Array tbuf; size_t padded_len; - if (!setup_tbuf(rctx, ctx) || - !RSA_decrypt(rsa, &padded_len, rctx->tbuf, key_len, in, inlen, + if (!tbuf.InitForOverwrite(key_len) || + !RSA_decrypt(rsa, &padded_len, tbuf.data(), tbuf.size(), in, inlen, RSA_NO_PADDING) || - !RSA_padding_check_PKCS1_OAEP_mgf1( - out, outlen, key_len, rctx->tbuf, padded_len, rctx->oaep_label, - rctx->oaep_labellen, rctx->md, rctx->mgf1md)) { + !RSA_padding_check_PKCS1_OAEP_mgf1(out, outlen, key_len, tbuf.data(), + padded_len, rctx->oaep_label.data(), + rctx->oaep_label.size(), rctx->md, + rctx->mgf1md)) { return 0; } return 1; @@ -357,6 +339,11 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { RSA_PKEY_CTX *rctx = reinterpret_cast(ctx->data); switch (type) { case EVP_PKEY_CTRL_RSA_PADDING: + // PSS keys cannot be switched to other padding types. + if (is_pss_only(ctx) && p1 != RSA_PKCS1_PSS_PADDING) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); + return 0; + } if (!is_known_padding(p1) || !check_padding_md(rctx->md, p1) || (p1 == RSA_PKCS1_PSS_PADDING && 0 == (ctx->operation & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) || @@ -365,8 +352,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OPENSSL_PUT_ERROR(EVP, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); return 0; } - if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) && - rctx->md == NULL) { + if (p1 == RSA_PKCS1_OAEP_PADDING && rctx->md == NULL) { rctx->md = EVP_sha1(); } rctx->pad_mode = p1; @@ -385,7 +371,21 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) { *(int *)p2 = rctx->saltlen; } else { - if (p1 < -2) { + // Negative salt lengths are special values. + if (p1 < 0) { + if (p1 != RSA_PSS_SALTLEN_DIGEST && p1 != RSA_PSS_SALTLEN_AUTO) { + return 0; + } + // All our PSS restrictions accept saltlen == hashlen, so allow + // |RSA_PSS_SALTLEN_DIGEST|. Reject |RSA_PSS_SALTLEN_AUTO| for + // simplicity. + if (rctx->restrict_pss_params && p1 != RSA_PSS_SALTLEN_DIGEST) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_SALTLEN); + return 0; + } + } else if (rctx->restrict_pss_params && + static_cast(p1) < EVP_MD_size(rctx->md)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_SALTLEN); return 0; } rctx->saltlen = p1; @@ -404,8 +404,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { if (!p2) { return 0; } - BN_free(rctx->pub_exp); - rctx->pub_exp = reinterpret_cast(p2); + rctx->pub_exp.reset(reinterpret_cast(p2)); return 1; case EVP_PKEY_CTRL_RSA_OAEP_MD: @@ -421,12 +420,19 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } return 1; - case EVP_PKEY_CTRL_MD: - if (!check_padding_md(reinterpret_cast(p2), rctx->pad_mode)) { + case EVP_PKEY_CTRL_MD: { + const EVP_MD *md = reinterpret_cast(p2); + if (!check_padding_md(md, rctx->pad_mode)) { return 0; } - rctx->md = reinterpret_cast(p2); + if (rctx->restrict_pss_params && + EVP_MD_type(rctx->md) != EVP_MD_type(md)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_TYPE); + return 0; + } + rctx->md = md; return 1; + } case EVP_PKEY_CTRL_GET_MD: *(const EVP_MD **)p2 = rctx->md; @@ -446,7 +452,13 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { *(const EVP_MD **)p2 = rctx->md; } } else { - rctx->mgf1md = reinterpret_cast(p2); + const EVP_MD *md = reinterpret_cast(p2); + if (rctx->restrict_pss_params && + EVP_MD_type(rctx->mgf1md) != EVP_MD_type(md)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_MGF1_MD); + return 0; + } + rctx->mgf1md = md; } return 1; @@ -455,11 +467,10 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); return 0; } - OPENSSL_free(rctx->oaep_label); - RSA_OAEP_LABEL_PARAMS *params = - reinterpret_cast(p2); - rctx->oaep_label = params->data; - rctx->oaep_labellen = params->len; + // |EVP_PKEY_CTRL_RSA_OAEP_LABEL| takes ownership of |label|'s underlying + // buffer (via |Reset|), but only on success. + auto *label = reinterpret_cast *>(p2); + rctx->oaep_label.Reset(label->data(), label->size()); return 1; } @@ -468,7 +479,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE); return 0; } - CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen); + *reinterpret_cast(p2) = CBS(rctx->oaep_label); return 1; default: @@ -478,90 +489,130 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { - RSA *rsa = NULL; RSA_PKEY_CTX *rctx = reinterpret_cast(ctx->data); - if (!rctx->pub_exp) { - rctx->pub_exp = BN_new(); - if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4)) { + rctx->pub_exp.reset(BN_new()); + if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp.get(), RSA_F4)) { return 0; } } - rsa = RSA_new(); + bssl::UniquePtr rsa(RSA_new()); if (!rsa) { return 0; } - if (!RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, NULL)) { - RSA_free(rsa); + if (!RSA_generate_key_ex(rsa.get(), rctx->nbits, rctx->pub_exp.get(), + nullptr)) { return 0; } - EVP_PKEY_assign_RSA(pkey, rsa); + EVP_PKEY_assign_RSA(pkey, rsa.release()); return 1; } -const EVP_PKEY_METHOD rsa_pkey_meth = { +} // namespace + +const EVP_PKEY_CTX_METHOD rsa_pkey_meth = { EVP_PKEY_RSA, pkey_rsa_init, pkey_rsa_copy, pkey_rsa_cleanup, pkey_rsa_keygen, pkey_rsa_sign, - NULL /* sign_message */, + /*sign_message=*/nullptr, pkey_rsa_verify, - NULL /* verify_message */, + /*verify_message=*/nullptr, pkey_rsa_verify_recover, pkey_rsa_encrypt, pkey_rsa_decrypt, - NULL /* derive */, - NULL /* paramgen */, + /*derive=*/nullptr, + /*paramgen=*/nullptr, + pkey_rsa_ctrl, +}; + +const EVP_PKEY_CTX_METHOD rsa_pss_sha256_pkey_meth = { + EVP_PKEY_RSA_PSS, + pkey_rsa_init, + pkey_rsa_copy, + pkey_rsa_cleanup, + // In OpenSSL, |EVP_PKEY_RSA_PSS| supports key generation and fills in PSS + // parameters based on a separate set of keygen-targetted setters: + // |EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen|, + // |EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md|, and + // |EVP_PKEY_CTX_rsa_pss_key_digest|. We do not currently implement this + // because we only support one parameter set. + /*keygen=*/nullptr, + pkey_rsa_sign, + /*sign_message=*/nullptr, + pkey_rsa_verify, + /*verify_message=*/nullptr, + /*verify_recover=*/nullptr, + /*encrypt=*/nullptr, + /*decrypt=*/nullptr, + /*derive=*/nullptr, + /*paramgen=*/nullptr, pkey_rsa_ctrl, }; +static int rsa_or_rsa_pss_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, + void *p2) { + if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } + if (ctx->pmeth->pkey_id != EVP_PKEY_RSA && + ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) { + OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return 0; + } + return EVP_PKEY_CTX_ctrl(ctx, /*keytype=*/-1, optype, cmd, p1, p2); +} + int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, - padding, NULL); + return rsa_or_rsa_pss_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, + nullptr); } int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, - 0, out_padding); + return rsa_or_rsa_pss_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, + out_padding); } int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { + // We currently do not support keygen with |EVP_PKEY_RSA_PSS|. return 0; } int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, int salt_len) { + // We currently do not support keygen with |EVP_PKEY_RSA_PSS|. return 0; } int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { + // We currently do not support keygen with |EVP_PKEY_RSA_PSS|. return 0; } int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, - (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), - EVP_PKEY_CTRL_RSA_PSS_SALTLEN, salt_len, NULL); + return rsa_or_rsa_pss_ctrl(ctx, (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, salt_len, nullptr); } int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *out_salt_len) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, - (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), - EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, out_salt_len); + return rsa_or_rsa_pss_ctrl(ctx, (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, + out_salt_len); } int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, - EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL); + return rsa_or_rsa_pss_ctrl(ctx, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, nullptr); } int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *e) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, - EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, e); + return rsa_or_rsa_pss_ctrl(ctx, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, e); } int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { @@ -575,22 +626,20 @@ int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { } int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, - EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md); + return rsa_or_rsa_pss_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md); } int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { - return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, - EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)out_md); + return rsa_or_rsa_pss_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)out_md); } int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, uint8_t *label, size_t label_len) { - RSA_OAEP_LABEL_PARAMS params = {label, label_len}; + bssl::Span span(label, label_len); return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, - EVP_PKEY_CTRL_RSA_OAEP_LABEL, 0, ¶ms); + EVP_PKEY_CTRL_RSA_OAEP_LABEL, 0, &span); } int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_rsa_asn1.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_rsa_asn1.cc index 682967835..8865b68a9 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_rsa_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_rsa_asn1.cc @@ -20,8 +20,10 @@ #include #include #include +#include #include "../fipsmodule/rsa/internal.h" +#include "../rsa/internal.h" #include "internal.h" @@ -45,7 +47,9 @@ static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t rsa_pub_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 3279, section 2.3.1. // The parameters must be NULL. @@ -53,21 +57,25 @@ static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || CBS_len(&null) != 0 || CBS_len(params) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } - RSA *rsa = RSA_parse_public_key(key); - if (rsa == NULL || CBS_len(key) != 0) { + bssl::UniquePtr rsa( + RSA_public_key_from_bytes(CBS_data(key), CBS_len(key))); + if (rsa == nullptr) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - RSA_free(rsa); - return 0; + return evp_decode_error; } - EVP_PKEY_assign_RSA(out, rsa); - return 1; + EVP_PKEY_assign_RSA(out, rsa.release()); + return evp_decode_ok; } static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { + // We currently assume that all |EVP_PKEY_RSA_PSS| keys have the same + // parameters, so this vacuously compares parameters. If we ever support + // multiple PSS parameter sets, we probably should compare them too. Note, + // however, that OpenSSL does not compare parameters here. const RSA *a_rsa = reinterpret_cast(a->pkey); const RSA *b_rsa = reinterpret_cast(b->pkey); return BN_cmp(RSA_get0_n(b_rsa), RSA_get0_n(a_rsa)) == 0 && @@ -93,26 +101,122 @@ static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) { return 1; } -static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { - // Per RFC 3447, A.1, the parameters have type NULL. +static evp_decode_result_t rsa_priv_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { + // Per RFC 8017, A.1, the parameters have type NULL. CBS null; if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || CBS_len(&null) != 0 || CBS_len(params) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return evp_decode_error; + } + + bssl::UniquePtr rsa( + RSA_private_key_from_bytes(CBS_data(key), CBS_len(key))); + if (rsa == nullptr) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return evp_decode_error; + } + + EVP_PKEY_assign_RSA(out, rsa.release()); + return evp_decode_ok; +} + +static evp_decode_result_t rsa_decode_pss_params_sha256(CBS *params) { + // For now, we only support the SHA-256 parameter set. If we want to support + // more, we'll need to record a little more state in the |EVP_PKEY|. + if (CBS_len(params) == 0) { + return evp_decode_unsupported; + } + rsa_pss_params_t pss_params; + if (!rsa_parse_pss_params(params, &pss_params, + /*allow_explicit_trailer=*/false) || + CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return evp_decode_error; + } + return pss_params == rsa_pss_sha256 ? evp_decode_ok : evp_decode_unsupported; +} + +static int rsa_pub_encode_pss_sha256(CBB *out, const EVP_PKEY *key) { + const RSA *rsa = reinterpret_cast(key->pkey); + CBB spki, algorithm, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, + rsa_pss_sha256_asn1_meth.oid, + rsa_pss_sha256_asn1_meth.oid_len) || + !rsa_marshal_pss_params(&algorithm, rsa_pss_sha256) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !RSA_marshal_public_key(&key_bitstring, rsa) || // + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); return 0; } - RSA *rsa = RSA_parse_private_key(key); - if (rsa == NULL || CBS_len(key) != 0) { + return 1; +} + +static evp_decode_result_t rsa_pub_decode_pss_sha256(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { + evp_decode_result_t ret = rsa_decode_pss_params_sha256(params); + if (ret != evp_decode_ok) { + return ret; + } + + bssl::UniquePtr rsa( + RSA_public_key_from_bytes(CBS_data(key), CBS_len(key))); + if (rsa == nullptr) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - RSA_free(rsa); + return evp_decode_error; + } + + evp_pkey_set0(out, &rsa_pss_sha256_asn1_meth, rsa.release()); + return evp_decode_ok; +} + +static int rsa_priv_encode_pss_sha256(CBB *out, const EVP_PKEY *key) { + const RSA *rsa = reinterpret_cast(key->pkey); + CBB pkcs8, algorithm, private_key; + if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || + !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, + rsa_pss_sha256_asn1_meth.oid, + rsa_pss_sha256_asn1_meth.oid_len) || + !rsa_marshal_pss_params(&algorithm, rsa_pss_sha256) || + !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || + !RSA_marshal_private_key(&private_key, rsa) || // + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); return 0; } - EVP_PKEY_assign_RSA(out, rsa); return 1; } +static evp_decode_result_t rsa_priv_decode_pss_sha256(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, + CBS *params, CBS *key) { + evp_decode_result_t ret = rsa_decode_pss_params_sha256(params); + if (ret != evp_decode_ok) { + return ret; + } + + bssl::UniquePtr rsa( + RSA_private_key_from_bytes(CBS_data(key), CBS_len(key))); + if (rsa == nullptr) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return evp_decode_error; + } + + evp_pkey_set0(out, &rsa_pss_sha256_asn1_meth, rsa.release()); + return evp_decode_ok; +} + static int rsa_opaque(const EVP_PKEY *pkey) { const RSA *rsa = reinterpret_cast(pkey->pkey); return RSA_is_opaque(rsa); @@ -148,25 +252,76 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = { rsa_priv_decode, rsa_priv_encode, - /*set_priv_raw=*/NULL, - /*set_pub_raw=*/NULL, - /*get_priv_raw=*/NULL, - /*get_pub_raw=*/NULL, - /*set1_tls_encodedpoint=*/NULL, - /*get1_tls_encodedpoint=*/NULL, + /*set_priv_raw=*/nullptr, + /*set_pub_raw=*/nullptr, + /*get_priv_raw=*/nullptr, + /*get_pub_raw=*/nullptr, + /*set1_tls_encodedpoint=*/nullptr, + /*get1_tls_encodedpoint=*/nullptr, + + rsa_opaque, + + int_rsa_size, + rsa_bits, + + /*param_missing=*/nullptr, + /*param_copy=*/nullptr, + /*param_cmp=*/nullptr, + + int_rsa_free, +}; + +const EVP_PKEY_ASN1_METHOD rsa_pss_sha256_asn1_meth = { + EVP_PKEY_RSA_PSS, + // 1.2.840.113549.1.1.10 + {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a}, + 9, + + &rsa_pss_sha256_pkey_meth, + + rsa_pub_decode_pss_sha256, + rsa_pub_encode_pss_sha256, + rsa_pub_cmp, + + rsa_priv_decode_pss_sha256, + rsa_priv_encode_pss_sha256, + + /*set_priv_raw=*/nullptr, + /*set_pub_raw=*/nullptr, + /*get_priv_raw=*/nullptr, + /*get_pub_raw=*/nullptr, + /*set1_tls_encodedpoint=*/nullptr, + /*get1_tls_encodedpoint=*/nullptr, rsa_opaque, int_rsa_size, rsa_bits, - 0, - 0, - 0, + /*param_missing=*/nullptr, + /*param_copy=*/nullptr, + /*param_cmp=*/nullptr, int_rsa_free, }; + +const EVP_PKEY_ALG *EVP_pkey_rsa(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&rsa_asn1_meth, + /*ec_group=*/nullptr, + }; + return &kAlg; +} + +const EVP_PKEY_ALG *EVP_pkey_rsa_pss_sha256(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&rsa_pss_sha256_asn1_meth, + /*ec_group=*/nullptr, + }; + return &kAlg; +} + int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) { if (EVP_PKEY_assign_RSA(pkey, key)) { RSA_up_ref(key); @@ -176,13 +331,16 @@ int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) { } int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) { - evp_pkey_set_method(pkey, &rsa_asn1_meth); - pkey->pkey = key; - return key != NULL; + if (key == nullptr) { + return 0; + } + evp_pkey_set0(pkey, &rsa_asn1_meth, key); + return 1; } RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey) { - if (pkey->type != EVP_PKEY_RSA) { + int pkey_id = EVP_PKEY_id(pkey); + if (pkey_id != EVP_PKEY_RSA && pkey_id != EVP_PKEY_RSA_PSS) { OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_RSA_KEY); return NULL; } diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_x25519.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_x25519.cc index da526bc96..6e3d23b35 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_x25519.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_x25519.cc @@ -31,13 +31,9 @@ static int pkey_x25519_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { return 0; } - evp_pkey_set_method(pkey, &x25519_asn1_meth); - X25519_keypair(key->pub, key->priv); key->has_private = 1; - - OPENSSL_free(pkey->pkey); - pkey->pkey = key; + evp_pkey_set0(pkey, &x25519_asn1_meth, key); return 1; } @@ -90,7 +86,7 @@ static int pkey_x25519_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { } } -const EVP_PKEY_METHOD x25519_pkey_meth = { +const EVP_PKEY_CTX_METHOD x25519_pkey_meth = { /*pkey_id=*/EVP_PKEY_X25519, /*init=*/NULL, /*copy=*/pkey_x25519_copy, diff --git a/Sources/CCryptoBoringSSL/crypto/evp/p_x25519_asn1.cc b/Sources/CCryptoBoringSSL/crypto/evp/p_x25519_asn1.cc index ced00a586..ed43ce3c3 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/p_x25519_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/p_x25519_asn1.cc @@ -44,8 +44,7 @@ static int x25519_set_priv_raw(EVP_PKEY *pkey, const uint8_t *in, size_t len) { X25519_public_from_private(key->pub, key->priv); key->has_private = 1; - x25519_free(pkey); - pkey->pkey = key; + evp_pkey_set0(pkey, &x25519_asn1_meth, key); return 1; } @@ -64,8 +63,7 @@ static int x25519_set_pub_raw(EVP_PKEY *pkey, const uint8_t *in, size_t len) { OPENSSL_memcpy(key->pub, in, 32); key->has_private = 0; - x25519_free(pkey); - pkey->pkey = key; + evp_pkey_set0(pkey, &x25519_asn1_meth, key); return 1; } @@ -127,16 +125,20 @@ static size_t x25519_get1_tls_encodedpoint(const EVP_PKEY *pkey, return *out_ptr == NULL ? 0 : 32; } -static int x25519_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t x25519_pub_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 8410, section 4. // The parameters must be omitted. Public keys have length 32. if (CBS_len(params) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } - return x25519_set_pub_raw(out, CBS_data(key), CBS_len(key)); + return x25519_set_pub_raw(out, CBS_data(key), CBS_len(key)) + ? evp_decode_ok + : evp_decode_error; } static int x25519_pub_encode(CBB *out, const EVP_PKEY *pkey) { @@ -165,7 +167,9 @@ static int x25519_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { return OPENSSL_memcmp(a_key->pub, b_key->pub, 32) == 0; } -static int x25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { +static evp_decode_result_t x25519_priv_decode(const EVP_PKEY_ALG *alg, + EVP_PKEY *out, CBS *params, + CBS *key) { // See RFC 8410, section 7. // Parameters must be empty. The key is a 32-byte value wrapped in an extra @@ -174,10 +178,12 @@ static int x25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { if (CBS_len(params) != 0 || !CBS_get_asn1(key, &inner, CBS_ASN1_OCTETSTRING) || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); - return 0; + return evp_decode_error; } - return x25519_set_priv_raw(out, CBS_data(&inner), CBS_len(&inner)); + return x25519_set_priv_raw(out, CBS_data(&inner), CBS_len(&inner)) + ? evp_decode_ok + : evp_decode_error; } static int x25519_priv_encode(CBB *out, const EVP_PKEY *pkey) { @@ -235,3 +241,11 @@ const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = { /*param_cmp=*/NULL, x25519_free, }; + +const EVP_PKEY_ALG *EVP_pkey_x25519(void) { + static const EVP_PKEY_ALG kAlg = { + /*method=*/&x25519_asn1_meth, + /*ec_group=*/nullptr, + }; + return &kAlg; +} diff --git a/Sources/CCryptoBoringSSL/crypto/evp/print.cc b/Sources/CCryptoBoringSSL/crypto/evp/print.cc index f052f89a7..718d8c79d 100644 --- a/Sources/CCryptoBoringSSL/crypto/evp/print.cc +++ b/Sources/CCryptoBoringSSL/crypto/evp/print.cc @@ -152,55 +152,6 @@ static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) { } -// DSA keys. - -static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) { - const BIGNUM *priv_key = NULL; - if (ptype == 2) { - priv_key = DSA_get0_priv_key(x); - } - - const BIGNUM *pub_key = NULL; - if (ptype > 0) { - pub_key = DSA_get0_pub_key(x); - } - - const char *ktype = "DSA-Parameters"; - if (ptype == 2) { - ktype = "Private-Key"; - } else if (ptype == 1) { - ktype = "Public-Key"; - } - - if (!BIO_indent(bp, off, 128) || - BIO_printf(bp, "%s: (%u bit)\n", ktype, BN_num_bits(DSA_get0_p(x))) <= - 0 || - // |priv_key| and |pub_key| may be NULL, in which case |bn_print| will - // silently skip them. - !bn_print(bp, "priv:", priv_key, off) || - !bn_print(bp, "pub:", pub_key, off) || - !bn_print(bp, "P:", DSA_get0_p(x), off) || - !bn_print(bp, "Q:", DSA_get0_q(x), off) || - !bn_print(bp, "G:", DSA_get0_g(x), off)) { - return 0; - } - - return 1; -} - -static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent) { - return do_dsa_print(bp, EVP_PKEY_get0_DSA(pkey), indent, 0); -} - -static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) { - return do_dsa_print(bp, EVP_PKEY_get0_DSA(pkey), indent, 1); -} - -static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) { - return do_dsa_print(bp, EVP_PKEY_get0_DSA(pkey), indent, 2); -} - - // EC keys. static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) { @@ -277,18 +228,12 @@ typedef struct { int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent); } EVP_PKEY_PRINT_METHOD; -static EVP_PKEY_PRINT_METHOD kPrintMethods[] = { +static const EVP_PKEY_PRINT_METHOD kPrintMethods[] = { { EVP_PKEY_RSA, rsa_pub_print, rsa_priv_print, - NULL /* param_print */, - }, - { - EVP_PKEY_DSA, - dsa_pub_print, - dsa_priv_print, - dsa_param_print, + /*param_print=*/nullptr, }, { EVP_PKEY_EC, @@ -298,15 +243,13 @@ static EVP_PKEY_PRINT_METHOD kPrintMethods[] = { }, }; -static size_t kPrintMethodsLen = OPENSSL_ARRAY_SIZE(kPrintMethods); - -static EVP_PKEY_PRINT_METHOD *find_method(int type) { - for (size_t i = 0; i < kPrintMethodsLen; i++) { - if (kPrintMethods[i].type == type) { - return &kPrintMethods[i]; +static const EVP_PKEY_PRINT_METHOD *find_method(int type) { + for (const auto &p : kPrintMethods) { + if (p.type == type) { + return &p; } } - return NULL; + return nullptr; } static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent, @@ -318,7 +261,7 @@ static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent, int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { - EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey)); + const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey)); if (method != NULL && method->pub_print != NULL) { return method->pub_print(out, pkey, indent); } @@ -327,7 +270,7 @@ int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { - EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey)); + const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey)); if (method != NULL && method->priv_print != NULL) { return method->priv_print(out, pkey, indent); } @@ -336,7 +279,7 @@ int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent, int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) { - EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey)); + const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey)); if (method != NULL && method->param_print != NULL) { return method->param_print(out, pkey, indent); } diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm.cc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm.cc index 6863c5535..257b2a260 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm.cc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm.cc @@ -26,7 +26,7 @@ #include #include -#include +#include #include "../bcm_support.h" #include "../internal.h" @@ -90,6 +90,7 @@ #include "ec/wnaf.cc.inc" #include "ecdh/ecdh.cc.inc" #include "ecdsa/ecdsa.cc.inc" +#include "entropy/jitter.cc.inc" #include "hkdf/hkdf.cc.inc" #include "hmac/hmac.cc.inc" #include "keccak/keccak.cc.inc" @@ -172,8 +173,8 @@ static void BORINGSSL_maybe_set_module_text_permissions(int permission) {} #endif // !ASAN -static void __attribute__((constructor)) -BORINGSSL_bcm_power_on_self_test(void) { +static void __attribute__((constructor)) BORINGSSL_bcm_power_on_self_test( + void) { #if !defined(OPENSSL_ASAN) // Integrity tests cannot run under ASAN because it involves reading the full // .text section, which triggers the global-buffer overflow detection. diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm_interface.h b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm_interface.h index d746fd8b7..14d64cb8c 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm_interface.h +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bcm_interface.h @@ -529,6 +529,140 @@ OPENSSL_EXPORT bcm_status BCM_mldsa87_verify_internal( OPENSSL_EXPORT bcm_status BCM_mldsa87_marshal_private_key( CBB *out, const struct BCM_mldsa87_private_key *private_key); +// BCM_MLDSA44_PRIVATE_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// private key. +#define BCM_MLDSA44_PRIVATE_KEY_BYTES 2560 + +// BCM_MLDSA44_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// public key. +#define BCM_MLDSA44_PUBLIC_KEY_BYTES 1312 + +// BCM_MLDSA44_SIGNATURE_BYTES is the number of bytes in an encoded ML-DSA-44 +// signature. +#define BCM_MLDSA44_SIGNATURE_BYTES 2420 + +struct BCM_mldsa44_private_key { + union { + uint8_t bytes[32 + 32 + 64 + 256 * 4 * (4 + 4 + 4)]; + uint32_t alignment; + } opaque; +}; + +struct BCM_mldsa44_public_key { + union { + uint8_t bytes[32 + 64 + 256 * 4 * 4]; + uint32_t alignment; + } opaque; +}; + +struct BCM_mldsa44_prehash { + union { + uint8_t bytes[200 + 4 + 4 + 4 * sizeof(size_t)]; + uint64_t alignment; + } opaque; +}; + +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_private_key_from_seed( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_public_from_private( + struct BCM_mldsa44_public_key *out_public_key, + const struct BCM_mldsa44_private_key *private_key); + +OPENSSL_EXPORT bcm_status +BCM_mldsa44_check_key_fips(struct BCM_mldsa44_private_key *private_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_private_key_from_seed_fips( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_sign( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context, size_t context_len); + +OPENSSL_EXPORT bcm_status +BCM_mldsa44_verify(const struct BCM_mldsa44_public_key *public_key, + const uint8_t *signature, const uint8_t *msg, size_t msg_len, + const uint8_t *context, size_t context_len); + +OPENSSL_EXPORT void BCM_mldsa44_prehash_init( + struct BCM_mldsa44_prehash *out_prehash_ctx, + const struct BCM_mldsa44_public_key *public_key, const uint8_t *context, + size_t context_len); + +OPENSSL_EXPORT void BCM_mldsa44_prehash_update( + struct BCM_mldsa44_prehash *inout_prehash_ctx, const uint8_t *msg, + size_t msg_len); + +OPENSSL_EXPORT void BCM_mldsa44_prehash_finalize( + uint8_t out_msg_rep[BCM_MLDSA_MU_BYTES], + struct BCM_mldsa44_prehash *inout_prehash_ctx); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_sign_message_representative( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, + const uint8_t msg_rep[BCM_MLDSA_MU_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_marshal_public_key( + CBB *out, const struct BCM_mldsa44_public_key *public_key); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_parse_public_key( + struct BCM_mldsa44_public_key *public_key, CBS *in); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_parse_private_key( + struct BCM_mldsa44_private_key *private_key, CBS *in); + +// BCM_mldsa44_generate_key_external_entropy generates a public/private key pair +// using the given seed, writes the encoded public key to +// |out_encoded_public_key| and sets |out_private_key| to the private key. +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key_external_entropy( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]); + +OPENSSL_EXPORT bcm_status BCM_mldsa44_generate_key_external_entropy_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]); + +// BCM_mldsa44_sign_internal signs |msg| using |private_key| and writes the +// signature to |out_encoded_signature|. The |context_prefix| and |context| are +// prefixed to the message, in that order, before signing. The |randomizer| +// value can be set to zero bytes in order to make a deterministic signature, or +// else filled with entropy for the usual |MLDSA_sign| behavior. +OPENSSL_EXPORT bcm_status BCM_mldsa44_sign_internal( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context_prefix, size_t context_prefix_len, + const uint8_t *context, size_t context_len, + const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]); + +// BCM_mldsa44_verify_internal verifies that |encoded_signature| is a valid +// signature of |msg| by |public_key|. The |context_prefix| and |context| are +// prefixed to the message before verification, in that order. +OPENSSL_EXPORT bcm_status BCM_mldsa44_verify_internal( + const struct BCM_mldsa44_public_key *public_key, + const uint8_t encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const uint8_t *msg, size_t msg_len, const uint8_t *context_prefix, + size_t context_prefix_len, const uint8_t *context, size_t context_len); + +// BCM_mldsa44_marshal_private_key serializes |private_key| to |out| in the +// NIST format for ML-DSA-44 private keys. +OPENSSL_EXPORT bcm_status BCM_mldsa44_marshal_private_key( + CBB *out, const struct BCM_mldsa44_private_key *private_key); + // ML-KEM // diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/exponentiation.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/exponentiation.cc.inc index ffcea64b6..3206708c0 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/exponentiation.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/exponentiation.cc.inc @@ -560,9 +560,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // |bn_mul_mont_gather5| and |bn_power5| implement the "almost" reduction // variant, so the values here may not be fully reduced. They are bounded by R // (i.e. they fit in |top| words), not |m|. Additionally, we pass these - // "almost" reduced inputs into |bn_mul_mont|, which implements the normal - // reduction variant. Given those inputs, |bn_mul_mont| may not give reduced - // output, but it will still produce "almost" reduced output. + // "almost" reduced inputs into |bn_mul_mont_words|, which implements the + // normal reduction variant. Given those inputs, |bn_mul_mont_words| may not + // give reduced output, but it will still produce "almost" reduced output. // // TODO(davidben): Using "almost" reduction complicates analysis of this code, // and its interaction with other parts of the project. Determine whether this @@ -578,12 +578,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BN_ULONG *n0 = mont->n0; bn_scatter5(tmp.d, top, powerbuf, 0); bn_scatter5(am.d, am.width, powerbuf, 1); - bn_mul_mont(tmp.d, am.d, am.d, np, n0, top); + bn_mul_mont_words(tmp.d, am.d, am.d, np, n0, top); bn_scatter5(tmp.d, top, powerbuf, 2); // Square to compute powers of two. for (i = 4; i < 32; i *= 2) { - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); bn_scatter5(tmp.d, top, powerbuf, i); } // Compute odd powers |i| based on |i - 1|, then all powers |i * 2^j|. @@ -591,7 +591,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); bn_scatter5(tmp.d, top, powerbuf, i); for (int j = 2 * i; j < 32; j *= 2) { - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); bn_scatter5(tmp.d, top, powerbuf, j); } } @@ -614,11 +614,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); } - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); - bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_words(tmp.d, tmp.d, tmp.d, np, n0, top); bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue); } } else { diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/generic.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/generic.cc.inc index 54d22f65f..90ee6acb1 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/generic.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/generic.cc.inc @@ -44,24 +44,24 @@ do { \ BN_ULLONG t; \ t = (BN_ULLONG)(w) * (a) + (r) + (c); \ - (r) = Lw(t); \ - (c) = Hw(t); \ + (r) = (BN_ULONG)(t); \ + (c) = (BN_ULONG)((t) >> BN_BITS2); \ } while (0) -#define mul(r, a, w, c) \ - do { \ - BN_ULLONG t; \ - t = (BN_ULLONG)(w) * (a) + (c); \ - (r) = Lw(t); \ - (c) = Hw(t); \ +#define mul(r, a, w, c) \ + do { \ + BN_ULLONG t; \ + t = (BN_ULLONG)(w) * (a) + (c); \ + (r) = (BN_ULONG)(t); \ + (c) = (BN_ULONG)((t) >> BN_BITS2); \ } while (0) -#define sqr(r0, r1, a) \ - do { \ - BN_ULLONG t; \ - t = (BN_ULLONG)(a) * (a); \ - (r0) = Lw(t); \ - (r1) = Hw(t); \ +#define sqr(r0, r1, a) \ + do { \ + BN_ULLONG t; \ + t = (BN_ULLONG)(a) * (a); \ + (r0) = (BN_ULONG)(t); \ + (r1) = (BN_ULONG)((t) >> BN_BITS2); \ } while (0) #else @@ -198,8 +198,8 @@ void bn_sqr_add_words(BN_ULONG *r, const BN_ULONG *a, size_t n) { BN_ULONG hi; \ BN_ULLONG t = (BN_ULLONG)(a) * (b); \ t += (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(t); \ - hi = (BN_ULONG)Hw(t); \ + (c0) = (BN_ULONG)(t); \ + hi = (BN_ULONG)((t) >> BN_BITS2); \ (c1) += (hi); \ (c2) += (c1) < hi; \ } while (0) @@ -209,13 +209,13 @@ void bn_sqr_add_words(BN_ULONG *r, const BN_ULONG *a, size_t n) { BN_ULONG hi; \ BN_ULLONG t = (BN_ULLONG)(a) * (b); \ BN_ULLONG tt = t + (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(tt); \ - hi = (BN_ULONG)Hw(tt); \ + (c0) = (BN_ULONG)(tt); \ + hi = (BN_ULONG)((tt) >> BN_BITS2); \ (c1) += hi; \ (c2) += (c1) < hi; \ t += (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(t); \ - hi = (BN_ULONG)Hw(t); \ + (c0) = (BN_ULONG)(t); \ + hi = (BN_ULONG)((t) >> BN_BITS2); \ (c1) += hi; \ (c2) += (c1) < hi; \ } while (0) @@ -225,8 +225,8 @@ void bn_sqr_add_words(BN_ULONG *r, const BN_ULONG *a, size_t n) { BN_ULONG hi; \ BN_ULLONG t = (BN_ULLONG)(a)[i] * (a)[i]; \ t += (c0); /* no carry */ \ - (c0) = (BN_ULONG)Lw(t); \ - hi = (BN_ULONG)Hw(t); \ + (c0) = (BN_ULONG)(t); \ + hi = (BN_ULONG)((t) >> BN_BITS2); \ (c1) += hi; \ (c2) += (c1) < hi; \ } while (0) diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/internal.h b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/internal.h index 289f86f53..a68a7d1af 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/internal.h @@ -105,11 +105,6 @@ extern "C" { sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \ } -#if defined(BN_ULLONG) -#define Lw(t) ((BN_ULONG)(t)) -#define Hw(t) ((BN_ULONG)((t) >> BN_BITS2)) -#endif - // bn_minimal_width returns the minimal number of words needed to represent // |bn|. int bn_minimal_width(const BIGNUM *bn); @@ -268,16 +263,27 @@ int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive, // |BIGNUM|s, in |bn_wexpand|, but the exactfloat library needs to create 8 MiB // values for other operations. // -// TODO(crbug.com/402677800): This is not quite tight enough to limit the -// |bn_mul_mont| allocation to under a page. Lower the maximum RSA key and then -// lower this to match. -#define BN_MONTGOMERY_MAX_WORDS (16384 / BN_BITS2) +// This limit is set so that one number fits within 1 KiB, giving room to +// allocate a few of them on the stack in |bn_mul_mont_words| without exceeding +// a page (4 KiB). It is also set to limit the DoS impact of large RSA, DH, and +// DSA keys, which scale cubically. +#define BN_MONTGOMERY_MAX_WORDS (8192 / BN_BITS2) + +struct bn_mont_ctx_st { + // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form. It + // is guaranteed to have the same width as |N|. + BIGNUM RR; + // N is the modulus. It is always stored in minimal form, so |N.width| + // determines R. + BIGNUM N; + BN_ULONG n0[BN_MONT_CTX_N0_LIMBS]; // least significant words of (R*Ri-1)/N +}; #if !defined(OPENSSL_NO_ASM) && \ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) #define OPENSSL_BN_ASM_MONT -// bn_mul_mont writes |ap| * |bp| mod |np| to |rp|, each |num| words +// bn_mul_mont_words writes |ap| * |bp| mod |np| to |rp|, each |num| words // long. Inputs and outputs are in Montgomery form. |n0| is a pointer to the // corresponding field in |BN_MONT_CTX|. // @@ -295,8 +301,9 @@ int bn_rand_secret_range(BIGNUM *r, int *out_is_uniform, BN_ULONG min_inclusive, // // See also discussion in |ToWord| in abi_test.h for notes on smaller-than-word // inputs. -void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); +void bn_mul_mont_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); #if defined(OPENSSL_X86_64) inline int bn_mulx_adx_capable(void) { @@ -304,30 +311,36 @@ inline int bn_mulx_adx_capable(void) { return CRYPTO_is_BMI2_capable() && CRYPTO_is_ADX_capable(); } void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); inline int bn_mul4x_mont_capable(size_t num) { return num >= 8 && (num & 3) == 0; } void bn_mul4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + size_t num); inline int bn_mulx4x_mont_capable(size_t num) { return bn_mul4x_mont_capable(num) && bn_mulx_adx_capable(); } void bn_mulx4x_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + size_t num); inline int bn_sqr8x_mont_capable(size_t num) { return num >= 8 && (num & 7) == 0; } void bn_sqr8x_mont(BN_ULONG *rp, const BN_ULONG *ap, BN_ULONG mulx_adx_capable, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + size_t num); #elif defined(OPENSSL_ARM) inline int bn_mul8x_mont_neon_capable(size_t num) { return (num & 7) == 0 && CRYPTO_is_NEON_capable(); } void bn_mul8x_mont_neon(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num); + const BN_ULONG *np, + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], size_t num); #endif #endif // OPENSSL_BN_ASM_MONT @@ -340,7 +353,8 @@ void bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, inline int bn_mul4x_mont_gather5_capable(int num) { return (num & 7) == 0; } void bn_mul4x_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, const BN_ULONG *np, - const BN_ULONG *n0, int num, int power); + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], int num, + int power); inline int bn_mulx4x_mont_gather5_capable(int num) { return bn_mul4x_mont_gather5_capable(num) && CRYPTO_is_ADX_capable() && @@ -348,11 +362,13 @@ inline int bn_mulx4x_mont_gather5_capable(int num) { } void bn_mulx4x_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, const BN_ULONG *np, - const BN_ULONG *n0, int num, int power); + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], int num, + int power); void bn_mul_mont_gather5_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, const BN_ULONG *np, - const BN_ULONG *n0, int num, int power); + const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], int num, + int power); // bn_scatter5 stores |inp| to index |power| of |table|. |inp| and each entry of // |table| are |num| words long. |power| must be less than 32 and is treated as @@ -368,7 +384,8 @@ void bn_gather5(BN_ULONG *out, size_t num, const BN_ULONG *table, size_t power); // The following functions implement |bn_power5|. See |bn_power5| for details. void bn_power5_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, - const BN_ULONG *np, const BN_ULONG *n0, int num, int power); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + int num, int power); inline int bn_power5_capable(int num) { return (num & 7) == 0; } @@ -377,7 +394,8 @@ inline int bn_powerx5_capable(int num) { CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable(); } void bn_powerx5(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, - const BN_ULONG *np, const BN_ULONG *n0, int num, int power); + const BN_ULONG *np, const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS], + int num, int power); #endif // !OPENSSL_NO_ASM && OPENSSL_X86_64 diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/montgomery.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/montgomery.cc.inc index 2746c060f..120ee218e 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/montgomery.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/montgomery.cc.inc @@ -64,8 +64,9 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from) { if (!BN_copy(&to->RR, &from->RR) || !BN_copy(&to->N, &from->N)) { return NULL; } - to->n0[0] = from->n0[0]; - to->n0[1] = from->n0[1]; + for (size_t i = 0; i < BN_MONT_CTX_N0_LIMBS; i++) { + to->n0[i] = from->n0[i]; + } return to; } @@ -111,8 +112,6 @@ static int bn_mont_ctx_set_N_and_n0(BN_MONT_CTX *mont, const BIGNUM *mod) { mont->n0[0] = (BN_ULONG)n0; #if BN_MONT_CTX_N0_LIMBS == 2 mont->n0[1] = (BN_ULONG)(n0 >> BN_BITS2); -#else - mont->n0[1] = 0; #endif return 1; } @@ -309,16 +308,16 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, } #if defined(OPENSSL_BN_ASM_MONT) - // |bn_mul_mont| requires at least 128 bits of limbs. + // |bn_mul_mont_words| requires at least 128 bits of limbs. int num = mont->N.width; if (num >= (128 / BN_BITS2) && a->width == num && b->width == num) { if (!bn_wexpand(r, num)) { return 0; } - // This bound is implied by |bn_mont_ctx_set_N_and_n0|. |bn_mul_mont| + // This bound is implied by |bn_mont_ctx_set_N_and_n0|. |bn_mul_mont_words| // allocates |num| words on the stack, so |num| cannot be too large. assert((size_t)num <= BN_MONTGOMERY_MAX_WORDS); - bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num); + bn_mul_mont_words(r->d, a->d, b->d, mont->N.d, mont->n0, num); r->neg = 0; r->width = num; return 1; @@ -359,9 +358,9 @@ void bn_mod_mul_montgomery_small(BN_ULONG *r, const BN_ULONG *a, } #if defined(OPENSSL_BN_ASM_MONT) - // |bn_mul_mont| requires at least 128 bits of limbs. + // |bn_mul_mont_words| requires at least 128 bits of limbs. if (num >= (128 / BN_BITS2)) { - bn_mul_mont(r, a, b, mont->N.d, mont->n0, num); + bn_mul_mont_words(r, a, b, mont->N.d, mont->n0, num); return; } #endif @@ -382,8 +381,8 @@ void bn_mod_mul_montgomery_small(BN_ULONG *r, const BN_ULONG *a, } #if defined(OPENSSL_BN_ASM_MONT) && defined(OPENSSL_X86_64) -void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num) { +void bn_mul_mont_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, size_t num) { if (ap == bp && bn_sqr8x_mont_capable(num)) { bn_sqr8x_mont(rp, ap, bn_mulx_adx_capable(), np, n0, num); } else if (bn_mulx4x_mont_capable(num)) { @@ -397,8 +396,8 @@ void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, #endif #if defined(OPENSSL_BN_ASM_MONT) && defined(OPENSSL_ARM) -void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, - const BN_ULONG *np, const BN_ULONG *n0, size_t num) { +void bn_mul_mont_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, size_t num) { if (bn_mul8x_mont_neon_capable(num)) { bn_mul8x_mont_neon(rp, ap, bp, np, n0, num); } else { diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/prime.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/prime.cc.inc index 4c8d440c9..1ba28018c 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/prime.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/bn/prime.cc.inc @@ -14,6 +14,8 @@ #include +#include + #include #include @@ -193,9 +195,9 @@ static int BN_prime_checks_for_size(int bits) { // of excluding a candidate with trial division is larger. static size_t num_trial_division_primes(const BIGNUM *n) { if (n->width * BN_BITS2 > 1024) { - return OPENSSL_ARRAY_SIZE(kPrimes); + return std::size(kPrimes); } - return OPENSSL_ARRAY_SIZE(kPrimes) / 2; + return std::size(kPrimes) / 2; } // BN_PRIME_CHECKS_BLINDED is the iteration count for blinding the constant-time diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/dh/dh.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/dh/dh.cc.inc index b7a883548..05ede8e07 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/dh/dh.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/dh/dh.cc.inc @@ -16,6 +16,8 @@ #include +#include + #include #include #include @@ -406,7 +408,7 @@ DH *DH_get_rfc7919_2048(void) { } bn_set_static_words(ffdhe2048_p.get(), kFFDHE2048Data, - OPENSSL_ARRAY_SIZE(kFFDHE2048Data)); + std::size(kFFDHE2048Data)); if (!BN_rshift1(ffdhe2048_q.get(), ffdhe2048_p.get()) || !BN_set_word(ffdhe2048_g.get(), 2) || diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digest.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digest.cc.inc index 622efd3f5..99c75b803 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digest.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digest.cc.inc @@ -36,7 +36,9 @@ size_t EVP_MD_block_size(const EVP_MD *md) { return md->block_size; } void EVP_MD_CTX_init(EVP_MD_CTX *ctx) { - OPENSSL_memset(ctx, 0, sizeof(EVP_MD_CTX)); + ctx->digest = nullptr; + ctx->pctx = nullptr; + ctx->pctx_ops = nullptr; } EVP_MD_CTX *EVP_MD_CTX_new(void) { @@ -53,8 +55,6 @@ EVP_MD_CTX *EVP_MD_CTX_new(void) { EVP_MD_CTX *EVP_MD_CTX_create(void) { return EVP_MD_CTX_new(); } int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) { - OPENSSL_free(ctx->md_data); - assert(ctx->pctx == NULL || ctx->pctx_ops != NULL); if (ctx->pctx_ops) { ctx->pctx_ops->free(ctx->pctx); @@ -66,7 +66,7 @@ int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) { } void EVP_MD_CTX_cleanse(EVP_MD_CTX *ctx) { - OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); + OPENSSL_cleanse(ctx->md_data, sizeof(ctx->md_data)); EVP_MD_CTX_cleanup(ctx); } @@ -97,6 +97,10 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) { OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_INPUT_NOT_INITIALIZED); return 0; } + if (out == in) { + OPENSSL_PUT_ERROR(DIGEST, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } EVP_PKEY_CTX *pctx = NULL; assert(in->pctx == NULL || in->pctx_ops != NULL); @@ -107,31 +111,9 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) { } } - uint8_t *tmp_buf = NULL; - if (in->digest != NULL) { - if (out->digest != in->digest) { - assert(in->digest->ctx_size != 0); - tmp_buf = - reinterpret_cast(OPENSSL_malloc(in->digest->ctx_size)); - if (tmp_buf == NULL) { - if (pctx) { - in->pctx_ops->free(pctx); - } - return 0; - } - } else { - // |md_data| will be the correct size in this case. It's removed from - // |out| so that |EVP_MD_CTX_cleanup| doesn't free it, and then it's - // reused. - tmp_buf = reinterpret_cast(out->md_data); - out->md_data = NULL; - } - } - EVP_MD_CTX_cleanup(out); out->digest = in->digest; - out->md_data = tmp_buf; if (in->digest != NULL) { OPENSSL_memcpy(out->md_data, in->md_data, in->digest->ctx_size); } @@ -167,14 +149,7 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) { int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) { if (ctx->digest != type) { assert(type->ctx_size != 0); - uint8_t *md_data = - reinterpret_cast(OPENSSL_malloc(type->ctx_size)); - if (md_data == NULL) { - return 0; - } - - OPENSSL_free(ctx->md_data); - ctx->md_data = md_data; + assert(type->ctx_size <= sizeof(ctx->md_data)); ctx->digest = type; } diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digests.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digests.cc.inc index 98bd7726f..40cc2263f 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digests.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/digest/digests.cc.inc @@ -54,6 +54,8 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha1) { out->ctx_size = sizeof(SHA_CTX); } +static_assert(sizeof(SHA_CTX) <= EVP_MAX_MD_DATA_SIZE); + static void sha224_init(EVP_MD_CTX *ctx) { BCM_sha224_init(reinterpret_cast(ctx->md_data)); @@ -78,6 +80,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha224) { out->ctx_size = sizeof(SHA256_CTX); } +static_assert(sizeof(SHA256_CTX) <= EVP_MAX_MD_DATA_SIZE); static void sha256_init(EVP_MD_CTX *ctx) { BCM_sha256_init(reinterpret_cast(ctx->md_data)); @@ -126,6 +129,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha384) { out->ctx_size = sizeof(SHA512_CTX); } +static_assert(sizeof(SHA512_CTX) <= EVP_MAX_MD_DATA_SIZE); static void sha512_init(EVP_MD_CTX *ctx) { BCM_sha512_init(reinterpret_cast(ctx->md_data)); diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/ec.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/ec.cc.inc index 4b5ff980c..aa3cb4309 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/ec.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/ec.cc.inc @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -64,10 +66,10 @@ DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p224) { OPENSSL_memcpy(out->oid, kOIDP224, sizeof(kOIDP224)); out->oid_len = sizeof(kOIDP224); - ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP224Field), - kP224Field, kP224FieldRR, kP224FieldN0); - ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP224Order), - kP224Order, kP224OrderRR, kP224OrderN0); + ec_group_init_static_mont(&out->field, std::size(kP224Field), kP224Field, + kP224FieldRR, kP224FieldN0); + ec_group_init_static_mont(&out->order, std::size(kP224Order), kP224Order, + kP224OrderRR, kP224OrderN0); #if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL) out->meth = EC_GFp_nistp224_method(); @@ -98,10 +100,10 @@ DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p256) { OPENSSL_memcpy(out->oid, kOIDP256, sizeof(kOIDP256)); out->oid_len = sizeof(kOIDP256); - ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP256Field), - kP256Field, kP256FieldRR, kP256FieldN0); - ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP256Order), - kP256Order, kP256OrderRR, kP256OrderN0); + ec_group_init_static_mont(&out->field, std::size(kP256Field), kP256Field, + kP256FieldRR, kP256FieldN0); + ec_group_init_static_mont(&out->order, std::size(kP256Order), kP256Order, + kP256OrderRR, kP256OrderN0); #if !defined(OPENSSL_NO_ASM) && \ (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \ @@ -129,10 +131,10 @@ DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p384) { OPENSSL_memcpy(out->oid, kOIDP384, sizeof(kOIDP384)); out->oid_len = sizeof(kOIDP384); - ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP384Field), - kP384Field, kP384FieldRR, kP384FieldN0); - ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP384Order), - kP384Order, kP384OrderRR, kP384OrderN0); + ec_group_init_static_mont(&out->field, std::size(kP384Field), kP384Field, + kP384FieldRR, kP384FieldN0); + ec_group_init_static_mont(&out->order, std::size(kP384Order), kP384Order, + kP384OrderRR, kP384OrderN0); out->meth = EC_GFp_mont_method(); out->generator.group = out; @@ -154,10 +156,10 @@ DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p521) { OPENSSL_memcpy(out->oid, kOIDP521, sizeof(kOIDP521)); out->oid_len = sizeof(kOIDP521); - ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP521Field), - kP521Field, kP521FieldRR, kP521FieldN0); - ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP521Order), - kP521Order, kP521OrderRR, kP521OrderN0); + ec_group_init_static_mont(&out->field, std::size(kP521Field), kP521Field, + kP521FieldRR, kP521FieldN0); + ec_group_init_static_mont(&out->order, std::size(kP521Order), kP521Order, + kP521OrderRR, kP521OrderN0); out->meth = EC_GFp_mont_method(); out->generator.group = out; @@ -870,7 +872,7 @@ void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask, const EC_PRECOMP *a, const EC_PRECOMP *b) { static_assert(sizeof(out->comb) == sizeof(*out), "out->comb does not span the entire structure"); - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(out->comb); i++) { + for (size_t i = 0; i < std::size(out->comb); i++) { ec_affine_select(group, &out->comb[i], mask, &a->comb[i], &b->comb[i]); } } diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/oct.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/oct.cc.inc index 8bb562055..27b46ec76 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/oct.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/oct.cc.inc @@ -262,9 +262,7 @@ int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, } if (!BN_mod_sqrt(y, tmp1, field, ctx)) { - uint32_t err = ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_BN && - ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { + if (ERR_equals(ERR_peek_last_error(), ERR_LIB_BN, BN_R_NOT_A_SQUARE)) { ERR_clear_error(); OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT); } else { diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256-nistz.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256-nistz.cc.inc index 9b1ffc44a..5a29419e6 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256-nistz.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256-nistz.cc.inc @@ -651,9 +651,9 @@ static void ecp_nistz256_inv0_mod_ord(const EC_GROUP *group, EC_SCALAR *out, {4, i_111}, {5, i_111}, {5, i_101}, {3, i_11}, {10, i_101111}, {2, i_11}, {5, i_11}, {5, i_11}, {3, i_1}, {7, i_10101}, {6, i_1111}}; - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kChain); i++) { - ecp_nistz256_ord_sqr_mont(out->words, out->words, kChain[i].p); - ecp_nistz256_ord_mul_mont(out->words, out->words, table[kChain[i].i]); + for (const auto &step : kChain) { + ecp_nistz256_ord_sqr_mont(out->words, out->words, step.p); + ecp_nistz256_ord_mul_mont(out->words, out->words, table[step.i]); } } diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256.cc.inc index 71a6fe18d..cdbff6268 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/p256.cc.inc @@ -26,18 +26,14 @@ #include #include +#include + #include "../../internal.h" #include "../delocate.h" #include "./internal.h" -#if defined(BORINGSSL_HAS_UINT128) -#include "../../../third_party/fiat/p256_64.h" -#elif defined(OPENSSL_64_BIT) -#include "../../../third_party/fiat/p256_64_msvc.h" -#else -#include "../../../third_party/fiat/p256_32.h" -#endif - +#include "../../../third_party/fiat/p256_field.c.inc" +#include "../../../third_party/fiat/p256_point.br.c.inc" // utility functions, handwritten @@ -56,13 +52,6 @@ static const fiat_p256_felem fiat_p256_one = { #endif // 64BIT -static fiat_p256_limb_t fiat_p256_nz( - const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) { - fiat_p256_limb_t ret; - fiat_p256_nonzero(&ret, in1); - return ret; -} - static void fiat_p256_copy(fiat_p256_limb_t out[FIAT_P256_NLIMBS], const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) { for (size_t i = 0; i < FIAT_P256_NLIMBS; i++) { @@ -172,198 +161,44 @@ static void fiat_p256_inv_square(fiat_p256_felem out, // Building on top of the field operations we have the operations on the // elliptic curve group itself. Points on the curve are represented in Jacobian // coordinates. -// -// Both operations were transcribed to Coq and proven to correspond to naive -// implementations using Affine coordinates, for all suitable fields. In the -// Coq proofs, issues of constant-time execution and memory layout (aliasing) -// conventions were not considered. Specification of affine coordinates: -// -// As a sanity check, a proof that these points form a commutative group: -// - -// fiat_p256_point_double calculates 2*(x_in, y_in, z_in) -// -// The method is taken from: -// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b -// -// Coq transcription and correctness proof: -// -// -// -// Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. -// while x_out == y_in is not (maybe this works, but it's not tested). + static void fiat_p256_point_double(fiat_p256_felem x_out, fiat_p256_felem y_out, fiat_p256_felem z_out, const fiat_p256_felem x_in, const fiat_p256_felem y_in, const fiat_p256_felem z_in) { - fiat_p256_felem delta, gamma, beta, ftmp, ftmp2, tmptmp, alpha, fourbeta; - // delta = z^2 - fiat_p256_square(delta, z_in); - // gamma = y^2 - fiat_p256_square(gamma, y_in); - // beta = x*gamma - fiat_p256_mul(beta, x_in, gamma); - - // alpha = 3*(x-delta)*(x+delta) - fiat_p256_sub(ftmp, x_in, delta); - fiat_p256_add(ftmp2, x_in, delta); - - fiat_p256_add(tmptmp, ftmp2, ftmp2); - fiat_p256_add(ftmp2, ftmp2, tmptmp); - fiat_p256_mul(alpha, ftmp, ftmp2); - - // x' = alpha^2 - 8*beta - fiat_p256_square(x_out, alpha); - fiat_p256_add(fourbeta, beta, beta); - fiat_p256_add(fourbeta, fourbeta, fourbeta); - fiat_p256_add(tmptmp, fourbeta, fourbeta); - fiat_p256_sub(x_out, x_out, tmptmp); - - // z' = (y + z)^2 - gamma - delta - fiat_p256_add(delta, gamma, delta); - fiat_p256_add(ftmp, y_in, z_in); - fiat_p256_square(z_out, ftmp); - fiat_p256_sub(z_out, z_out, delta); - - // y' = alpha*(4*beta - x') - 8*gamma^2 - fiat_p256_sub(y_out, fourbeta, x_out); - fiat_p256_add(gamma, gamma, gamma); - fiat_p256_square(gamma, gamma); - fiat_p256_mul(y_out, alpha, y_out); - fiat_p256_add(gamma, gamma, gamma); - fiat_p256_sub(y_out, y_out, gamma); + uint8_t out[3*32], in[3*32]; + static_assert(sizeof(fiat_p256_felem) == 32); + OPENSSL_memcpy(&in[0], x_in, 32); + OPENSSL_memcpy(&in[32], y_in, 32); + OPENSSL_memcpy(&in[64], z_in, 32); + p256_point_double((br_word_t)out, (br_word_t)in); + OPENSSL_memcpy(x_out, &out[0], 32); + OPENSSL_memcpy(y_out, &out[32], 32); + OPENSSL_memcpy(z_out, &out[64], 32); } -// fiat_p256_point_add calculates (x1, y1, z1) + (x2, y2, z2) -// -// The method is taken from: -// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, -// adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity). -// -// Coq transcription and correctness proof: -// -// -// -// This function includes a branch for checking whether the two input points -// are equal, (while not equal to the point at infinity). This case never -// happens during single point multiplication, so there is no timing leak for -// ECDH or ECDSA signing. static void fiat_p256_point_add(fiat_p256_felem x3, fiat_p256_felem y3, fiat_p256_felem z3, const fiat_p256_felem x1, const fiat_p256_felem y1, - const fiat_p256_felem z1, const int mixed, + const fiat_p256_felem z1, const fiat_p256_felem x2, const fiat_p256_felem y2, const fiat_p256_felem z2) { - fiat_p256_felem x_out, y_out, z_out; - fiat_p256_limb_t z1nz = fiat_p256_nz(z1); - fiat_p256_limb_t z2nz = fiat_p256_nz(z2); - - // z1z1 = z1z1 = z1**2 - fiat_p256_felem z1z1; - fiat_p256_square(z1z1, z1); - - fiat_p256_felem u1, s1, two_z1z2; - if (!mixed) { - // z2z2 = z2**2 - fiat_p256_felem z2z2; - fiat_p256_square(z2z2, z2); - - // u1 = x1*z2z2 - fiat_p256_mul(u1, x1, z2z2); - - // two_z1z2 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 - fiat_p256_add(two_z1z2, z1, z2); - fiat_p256_square(two_z1z2, two_z1z2); - fiat_p256_sub(two_z1z2, two_z1z2, z1z1); - fiat_p256_sub(two_z1z2, two_z1z2, z2z2); - - // s1 = y1 * z2**3 - fiat_p256_mul(s1, z2, z2z2); - fiat_p256_mul(s1, s1, y1); - } else { - // We'll assume z2 = 1 (special case z2 = 0 is handled later). - - // u1 = x1*z2z2 - fiat_p256_copy(u1, x1); - // two_z1z2 = 2z1z2 - fiat_p256_add(two_z1z2, z1, z1); - // s1 = y1 * z2**3 - fiat_p256_copy(s1, y1); - } - - // u2 = x2*z1z1 - fiat_p256_felem u2; - fiat_p256_mul(u2, x2, z1z1); - - // h = u2 - u1 - fiat_p256_felem h; - fiat_p256_sub(h, u2, u1); - - fiat_p256_limb_t xneq = fiat_p256_nz(h); - - // z_out = two_z1z2 * h - fiat_p256_mul(z_out, h, two_z1z2); - - // z1z1z1 = z1 * z1z1 - fiat_p256_felem z1z1z1; - fiat_p256_mul(z1z1z1, z1, z1z1); - - // s2 = y2 * z1**3 - fiat_p256_felem s2; - fiat_p256_mul(s2, y2, z1z1z1); - - // r = (s2 - s1)*2 - fiat_p256_felem r; - fiat_p256_sub(r, s2, s1); - fiat_p256_add(r, r, r); - - fiat_p256_limb_t yneq = fiat_p256_nz(r); - - fiat_p256_limb_t is_nontrivial_double = constant_time_is_zero_w(xneq | yneq) & - ~constant_time_is_zero_w(z1nz) & - ~constant_time_is_zero_w(z2nz); - if (constant_time_declassify_w(is_nontrivial_double)) { - fiat_p256_point_double(x3, y3, z3, x1, y1, z1); - return; - } - - // I = (2h)**2 - fiat_p256_felem i; - fiat_p256_add(i, h, h); - fiat_p256_square(i, i); - - // J = h * I - fiat_p256_felem j; - fiat_p256_mul(j, h, i); - - // V = U1 * I - fiat_p256_felem v; - fiat_p256_mul(v, u1, i); - - // x_out = r**2 - J - 2V - fiat_p256_square(x_out, r); - fiat_p256_sub(x_out, x_out, j); - fiat_p256_sub(x_out, x_out, v); - fiat_p256_sub(x_out, x_out, v); - - // y_out = r(V-x_out) - 2 * s1 * J - fiat_p256_sub(y_out, v, x_out); - fiat_p256_mul(y_out, y_out, r); - fiat_p256_felem s1j; - fiat_p256_mul(s1j, s1, j); - fiat_p256_sub(y_out, y_out, s1j); - fiat_p256_sub(y_out, y_out, s1j); - - fiat_p256_cmovznz(x_out, z1nz, x2, x_out); - fiat_p256_cmovznz(x3, z2nz, x1, x_out); - fiat_p256_cmovznz(y_out, z1nz, y2, y_out); - fiat_p256_cmovznz(y3, z2nz, y1, y_out); - fiat_p256_cmovznz(z_out, z1nz, z2, z_out); - fiat_p256_cmovznz(z3, z2nz, z1, z_out); + uint8_t out[3 * 32], in1[3 * 32], in2[3 * 32]; + static_assert(sizeof(fiat_p256_felem) == 32); + OPENSSL_memcpy(&in1[0], x1, 32); + OPENSSL_memcpy(&in1[32], y1, 32); + OPENSSL_memcpy(&in1[64], z1, 32); + OPENSSL_memcpy(&in2[0], x2, 32); + OPENSSL_memcpy(&in2[32], y2, 32); + OPENSSL_memcpy(&in2[64], z2, 32); + p256_point_add_vartime_if_doubling((br_word_t)out, (br_word_t)in1, + (br_word_t)in2); + OPENSSL_memcpy(x3, &out[0], 32); + OPENSSL_memcpy(y3, &out[32], 32); + OPENSSL_memcpy(z3, &out[64], 32); } - #include "./p256_table.h" // fiat_p256_select_point_affine selects the |idx-1|th point from a @@ -454,8 +289,7 @@ static void ec_GFp_nistp256_add(const EC_GROUP *group, EC_JACOBIAN *r, fiat_p256_from_generic(x2, &b->X); fiat_p256_from_generic(y2, &b->Y); fiat_p256_from_generic(z2, &b->Z); - fiat_p256_point_add(x1, y1, z1, x1, y1, z1, 0 /* both Jacobian */, x2, y2, - z2); + fiat_p256_point_add(x1, y1, z1, x1, y1, z1, x2, y2, z2); fiat_p256_to_generic(&r->X, x1); fiat_p256_to_generic(&r->Y, y1); fiat_p256_to_generic(&r->Z, z1); @@ -486,7 +320,7 @@ static void ec_GFp_nistp256_point_mul(const EC_GROUP *group, EC_JACOBIAN *r, if (j & 1) { fiat_p256_point_add(p_pre_comp[j][0], p_pre_comp[j][1], p_pre_comp[j][2], p_pre_comp[1][0], p_pre_comp[1][1], p_pre_comp[1][2], - 0, p_pre_comp[j - 1][0], p_pre_comp[j - 1][1], + p_pre_comp[j - 1][0], p_pre_comp[j - 1][1], p_pre_comp[j - 1][2]); } else { fiat_p256_point_double(p_pre_comp[j][0], p_pre_comp[j][1], @@ -524,8 +358,8 @@ static void ec_GFp_nistp256_point_mul(const EC_GROUP *group, EC_JACOBIAN *r, fiat_p256_cmovznz(tmp[1], (fiat_p256_limb_t)sign, tmp[1], ftmp); if (!skip) { - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], - 0 /* mixed */, tmp[0], tmp[1], tmp[2]); + fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], tmp[0], + tmp[1], tmp[2]); } else { fiat_p256_copy(nq[0], tmp[0]); fiat_p256_copy(nq[1], tmp[1]); @@ -562,8 +396,8 @@ static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group, fiat_p256_g_pre_comp[1], tmp); if (!skip) { - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); + fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], tmp[0], + tmp[1], tmp[2]); } else { fiat_p256_copy(nq[0], tmp[0]); fiat_p256_copy(nq[1], tmp[1]); @@ -579,8 +413,8 @@ static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group, // Select the point to add, in constant time. fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15, fiat_p256_g_pre_comp[0], tmp); - fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, - tmp[0], tmp[1], tmp[2]); + fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], tmp[0], + tmp[1], tmp[2]); } fiat_p256_to_generic(&r->X, nq[0]); @@ -602,11 +436,10 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, fiat_p256_felem p2[3]; fiat_p256_point_double(p2[0], p2[1], p2[2], p_pre_comp[0][0], p_pre_comp[0][1], p_pre_comp[0][2]); - for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) { + for (size_t i = 1; i < std::size(p_pre_comp); i++) { fiat_p256_point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2], p_pre_comp[i - 1][0], p_pre_comp[i - 1][1], - p_pre_comp[i - 1][2], 0 /* not mixed */, p2[0], p2[1], - p2[2]); + p_pre_comp[i - 1][2], p2[0], p2[1], p2[2]); } // Set up the coefficients for |p_scalar|. @@ -632,9 +465,8 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, if (bits != 0) { size_t index = (size_t)(bits - 1); fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 1 /* mixed */, fiat_p256_g_pre_comp[1][index][0], - fiat_p256_g_pre_comp[1][index][1], - fiat_p256_one); + fiat_p256_g_pre_comp[1][index][0], + fiat_p256_g_pre_comp[1][index][1], fiat_p256_one); skip = 0; } @@ -646,9 +478,8 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, if (bits != 0) { size_t index = (size_t)(bits - 1); fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 1 /* mixed */, fiat_p256_g_pre_comp[0][index][0], - fiat_p256_g_pre_comp[0][index][1], - fiat_p256_one); + fiat_p256_g_pre_comp[0][index][0], + fiat_p256_g_pre_comp[0][index][1], fiat_p256_one); skip = 0; } } @@ -664,8 +495,7 @@ static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, } if (!skip) { fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], - 0 /* not mixed */, p_pre_comp[idx][0], *y, - p_pre_comp[idx][2]); + p_pre_comp[idx][0], *y, p_pre_comp[idx][2]); } else { fiat_p256_copy(ret[0], p_pre_comp[idx][0]); fiat_p256_copy(ret[1], *y); diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/simple_mul.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/simple_mul.cc.inc index 2b659e205..cbe12bce6 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/simple_mul.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/simple_mul.cc.inc @@ -16,6 +16,9 @@ #include +#include +#include + #include "internal.h" #include "../bn/internal.h" #include "../../internal.h" @@ -31,7 +34,7 @@ void ec_GFp_mont_mul(const EC_GROUP *group, EC_JACOBIAN *r, EC_JACOBIAN precomp[32]; ec_GFp_simple_point_set_to_infinity(group, &precomp[0]); ec_GFp_simple_point_copy(&precomp[1], p); - for (size_t j = 2; j < OPENSSL_ARRAY_SIZE(precomp); j++) { + for (size_t j = 2; j < std::size(precomp); j++) { if (j & 1) { ec_GFp_mont_add(group, &precomp[j], &precomp[1], &precomp[j - 1]); } else { @@ -58,7 +61,7 @@ void ec_GFp_mont_mul(const EC_GROUP *group, EC_JACOBIAN *r, // Select the entry in constant-time. EC_JACOBIAN tmp; OPENSSL_memset(&tmp, 0, sizeof(EC_JACOBIAN)); - for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(precomp); j++) { + for (size_t j = 0; j < std::size(precomp); j++) { BN_ULONG mask = constant_time_eq_w(j, window); ec_point_select(group, &tmp, mask, &precomp[j], &tmp); } @@ -202,10 +205,10 @@ int ec_GFp_mont_init_precomp(const EC_GROUP *group, EC_PRECOMP *out, // Store the comb in affine coordinates to shrink the table. (This reduces // cache pressure and makes the constant-time selects faster.) - static_assert(OPENSSL_ARRAY_SIZE(comb) == OPENSSL_ARRAY_SIZE(out->comb), - "comb sizes did not match"); - return ec_jacobian_to_affine_batch(group, out->comb, comb, - OPENSSL_ARRAY_SIZE(comb)); + static_assert( + std::extent_v == std::extent_vcomb)>, + "comb sizes did not match"); + return ec_jacobian_to_affine_batch(group, out->comb, comb, std::size(comb)); } static void ec_GFp_mont_get_comb_window(const EC_GROUP *group, @@ -224,7 +227,7 @@ static void ec_GFp_mont_get_comb_window(const EC_GROUP *group, // Select precomp->comb[window - 1]. If |window| is zero, |match| will always // be zero, which will leave |out| at infinity. OPENSSL_memset(out, 0, sizeof(EC_JACOBIAN)); - for (unsigned j = 0; j < OPENSSL_ARRAY_SIZE(precomp->comb); j++) { + for (unsigned j = 0; j < std::size(precomp->comb); j++) { BN_ULONG match = constant_time_eq_w(window, j + 1); ec_felem_select(group, &out->X, match, &precomp->comb[j].X, &out->X); ec_felem_select(group, &out->Y, match, &precomp->comb[j].Y, &out->Y); diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/wnaf.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/wnaf.cc.inc index c3cc06d42..e8e1575e3 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/wnaf.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/ec/wnaf.cc.inc @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -167,7 +169,7 @@ int ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_JACOBIAN *r, int8_t g_wNAF[EC_MAX_BYTES * 8 + 1]; EC_JACOBIAN g_precomp[EC_WNAF_TABLE_SIZE]; - assert(wNAF_len <= OPENSSL_ARRAY_SIZE(g_wNAF)); + assert(wNAF_len <= std::size(g_wNAF)); const EC_JACOBIAN *g = &group->generator.raw; if (g_scalar != NULL) { ec_compute_wNAF(group, g_wNAF, g_scalar, bits, EC_WNAF_WINDOW_BITS); @@ -175,7 +177,7 @@ int ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_JACOBIAN *r, } for (size_t i = 0; i < num; i++) { - assert(wNAF_len <= OPENSSL_ARRAY_SIZE(wNAF[i])); + assert(wNAF_len <= std::size(wNAF[i])); ec_compute_wNAF(group, wNAF[i], &scalars[i], bits, EC_WNAF_WINDOW_BITS); compute_precomp(group, precomp[i], &points[i], EC_WNAF_TABLE_SIZE); } diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/internal.h b/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/internal.h new file mode 100644 index 000000000..27affb47d --- /dev/null +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/internal.h @@ -0,0 +1,38 @@ +// Copyright 2025 The BoringSSL Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_ENTROPY_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_ENTROPY_INTERNAL_H + +#include + +#if defined(OPENSSL_LINUX) || defined(OPENSSL_MACOS) + +BSSL_NAMESPACE_BEGIN +namespace entropy { + +// GetSeed fills `out` with random bytes from the jitter source. +OPENSSL_EXPORT bool GetSeed(uint8_t out[48]); + +// GetSamples fetches `n` raw delta time samples. +OPENSSL_EXPORT bool GetSamples(uint64_t *out, size_t n); + +// GetVersion returns the version of the entropy module. +int GetVersion(); + +} // namespace entropy +BSSL_NAMESPACE_END + +#endif // LINUX || MACOS +#endif // OPENSSL_HEADER_CRYPTO_FIPSMODULE_ENTROPY_INTERNAL_H diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/jitter.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/jitter.cc.inc new file mode 100644 index 000000000..4b94acf18 --- /dev/null +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/jitter.cc.inc @@ -0,0 +1,463 @@ +// Copyright 2025 The BoringSSL Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// BoringCrypto Jitter Entropy version 20250725. + +#include + +#if defined(OPENSSL_LINUX) || defined(OPENSSL_MACOS) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "internal.h" +#include "sha512.cc.inc" + +#if defined(__x86_64__) +#include +#endif + + +BSSL_NAMESPACE_BEGIN +namespace entropy { +namespace { + +#if defined(__x86_64__) +static inline uint64_t GetTimestamp() { return _rdtsc(); } +#elif defined(__aarch64__) +static inline uint64_t GetTimestamp() { + // Ideally this would use __arm_rsr64 from . Clang has supported + // it Clang 3.7 (2016), but GCC did not add it until GCC 14.1.0 (2024). See + // https://crbug.com/440670941. When our minimum GCC is past that point, + // switch this back to __arm_rsr64. + uint64_t ret; + __asm__ volatile("mrs %0, cntvct_el0" : "=r"(ret)); + return ret; +} +#else +static inline uint64_t GetTimestamp() { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + return ts.tv_sec * 1000000000ULL + ts.tv_nsec; +} +#endif + +class MemoryOffsetLCG { + public: + MemoryOffsetLCG() : state(GetTimestamp() & 0xFFFFFFFF) {} + uint32_t Next() { + state = state * 1664525 + 1013904223; + return state; + } + + private: + uint32_t state; +}; + +class MemoryAccessSampler { + public: + MemoryAccessSampler(size_t array_size, unsigned num_samples) + : array_size_(array_size), + num_samples_(num_samples), + array_(reinterpret_cast(OPENSSL_malloc(array_size_))) { + if (array_ == nullptr || // + array_size_ == 0 || // + array_size_ > (1u << 26) || // + array_size_ & (array_size_ - 1)) { + abort(); + } + } + + ~MemoryAccessSampler() { OPENSSL_free(const_cast(array_)); } + + MemoryAccessSampler(const MemoryAccessSampler &) = delete; + MemoryAccessSampler &operator=(const MemoryAccessSampler &) = delete; + + MemoryAccessSampler(MemoryAccessSampler &&other) + : array_size_(other.array_size_), + num_samples_(other.num_samples_), + lcg_(other.lcg_), + array_(other.array_) { + other.array_ = nullptr; + } + + bool Next(uint64_t *out) { + // Perform some memory accesses and measure how long it took. The LCG is + // intended to defeat any CPU predictors and thus expose this code to as + // much system entropy as possible. + for (unsigned i = 0; i < num_samples_; i++) { + // The lower bits of an LCG tend to fall into short cycles and so are + // discarded here. + array_[(lcg_.Next() >> 6) & (array_size_ - 1)] += 1; + } + + *out = GetTimestamp(); + return true; + } + + private: + const size_t array_size_; + const unsigned num_samples_; + MemoryOffsetLCG lcg_; + volatile uint8_t *array_; +}; + +template +class DeltaSampler { + public: + explicit DeltaSampler(T &&sub_sampler) + : sub_sampler_(std::forward(sub_sampler)) {} + + // Next function to return the delta between two subsequent samples + bool Next(uint64_t *out) { + uint64_t sample; + if (!sub_sampler_.Next(&sample)) { + return false; + } + + if (!initialized_) { + last_sample_ = sample; + if (!sub_sampler_.Next(&sample)) { + return false; + } + initialized_ = true; + } + + *out = sample - last_sample_; + last_sample_ = sample; + return true; + } + + private: + bool initialized_ = false; + T sub_sampler_; + uint64_t last_sample_; +}; + +template +DeltaSampler(U &&sub_sampler) -> DeltaSampler>; + +template +class MaskSampler { + public: + explicit MaskSampler(uint8_t mask, T &&sub_sampler) + : mask_(mask), sub_sampler_(std::forward(sub_sampler)) {} + + bool Next(uint8_t *out) { + uint64_t sample; + if (!sub_sampler_.Next(&sample)) { + return false; + } + + *out = sample & mask_; + return true; + } + + private: + const uint8_t mask_; + T sub_sampler_; +}; + +template +MaskSampler(uint8_t mask, U &&sub_sampler) -> MaskSampler>; + +// The estimated entropy per sample from MaskSampler. +constexpr float kH = 0.8; + +// kAlphaLog2 is log_2(alpha), where alpha is the standard false-positive +// probability from SP 800-90B. +static constexpr float kAlphaLog2 = -20; +// kAlpha is the variable of the same name from section 4.4.1 of SP 800-90B. +constexpr float kAlpha = 1.0 / (1 << static_cast(-kAlphaLog2)); + +// Ceil rounds up its non-negative argument to the next integer. (std::ceil +// isn't constexpr until C++23.) +constexpr unsigned Ceil(float val) { + auto truncated = static_cast(val); + if (val == static_cast(truncated)) { + return truncated; + } + if (val > 0) { + return truncated + 1; + } + __builtin_unreachable(); +} + +template +class RepetitionCountTest { + public: + static constexpr unsigned kThreshold = 1 + Ceil(-kAlphaLog2 / kH); + static_assert(kThreshold == 26); + + explicit RepetitionCountTest(T &&sub_sampler) + : sub_sampler_(std::forward(sub_sampler)) {} + + bool Next(uint8_t *out) { + uint8_t sample; + if (!sub_sampler_.Next(&sample)) { + return false; + } + if (sample == last_sample_) { + count_++; + } else { + count_ = 1; + last_sample_ = sample; + } + if (count_ >= kThreshold) { + return false; + } + *out = sample; + return true; + } + + private: + T sub_sampler_; + unsigned count_ = 0; + uint8_t last_sample_ = 0; +}; + +template +RepetitionCountTest(U &&sub_sampler) -> RepetitionCountTest>; + +constexpr double BinomialPMF(int64_t k, int64_t n, double p) { + if (k < 0 || k > n) { + return 0.0; + } + + double result = 1.0; + for (int64_t i = 0; i < k; ++i) { + result *= (n - i); + result /= (i + 1); + } + + for (int64_t i = 0; i < k; ++i) { + result *= p; + } + for (int64_t i = 0; i < n - k; ++i) { + result *= (1 - p); + } + + return result; +} + +// CritBinom implements the Excel function of the same name. +constexpr unsigned CritBinom(unsigned trials, double probability_s, + double alpha) { + if (probability_s < 0.0 || probability_s > 1.0 || alpha < 0.0 || + alpha > 1.0) { + __builtin_unreachable(); + } + + double cumulative = 0.0; + for (unsigned k = 0; k <= trials; ++k) { + cumulative += BinomialPMF(k, trials, probability_s); + if (cumulative >= alpha) { + return k; + } + } + + return trials; +} + +// ExpTaylor calculates e^x using the Taylor series: e^x = 1 + x + x²/2! + +// x³/3! + ... +constexpr double ExpTaylor(double x) { + double sum = 1.0; + double term = 1.0; + + for (int i = 1; i < 25; ++i) { + term *= x / i; + sum += term; + } + + return sum; +} + +// Power2 calculates 2^exp by calculating e^(ln(2) * exp) = e^(ln(2)) ^ exp = +// 2^exp. (std::pow isn't constexpr until C++26.) +constexpr double Power2(double exp) { + constexpr double ln2 = 0.693147180559945309417232121458; + return ExpTaylor(exp * ln2); +} + +// AdaptiveProportionTestCutoff implements the function from the footnote on +// page 27 of SP 800-90B. +constexpr unsigned AdaptiveProportionTestCutoff(unsigned W, float H, + float alpha) { + return 1 + CritBinom(W, Power2(-H), 1.0 - alpha); +} + +// These are the example values from table 2 of SP 800-90B, to show that +// we're calculating the values correctly. +static_assert(AdaptiveProportionTestCutoff(512, 0.5, kAlpha) == 410); +static_assert(AdaptiveProportionTestCutoff(512, 1, kAlpha) == 311); +static_assert(AdaptiveProportionTestCutoff(512, 2, kAlpha) == 177); +static_assert(AdaptiveProportionTestCutoff(512, 4, kAlpha) == 62); +static_assert(AdaptiveProportionTestCutoff(512, 8, kAlpha) == 13); + +template +class AdaptiveProportionTest { + public: + // The size of the sliding window, representing the number of recent samples + // to analyze. + static constexpr unsigned kWindowSize = 512; + + // The maximum number of times any single byte value is allowed to appear + // within the sliding window. + static constexpr unsigned kThreshold = + AdaptiveProportionTestCutoff(kWindowSize, kH, kAlpha); + static_assert(kThreshold == 348); + + explicit AdaptiveProportionTest(T &&sub_sampler) + : sub_sampler_(std::forward(sub_sampler)) { + counts_.fill(0); + } + + bool Next(uint8_t *out) { + uint8_t sample; + if (!sub_sampler_.Next(&sample)) { + return false; + } + *out = sample; + + if (samples_processed_ >= kWindowSize) { + const uint8_t evicted_sample = buffer_[buffer_idx_]; + counts_[evicted_sample]--; + } + + buffer_[buffer_idx_] = sample; + const uint16_t new_count = ++counts_[sample]; + + if (new_count > kThreshold) { + return false; + } + + buffer_idx_ = (buffer_idx_ + 1) % kWindowSize; + samples_processed_++; + + return true; + } + + private: + T sub_sampler_; + + // A circular buffer to store the most recent `kWindowSize` samples. + std::array buffer_{}; + + // An array to store the frequency counts of each possible byte value (0-255) + // within the current window. + std::array counts_{}; + + // The current index for writing into the circular buffer. + size_t buffer_idx_ = 0; + + // The total number of samples processed. Used to determine when the buffer + // is full and eviction should begin. + size_t samples_processed_ = 0; +}; + +template +AdaptiveProportionTest(U &&sub_sampler) + -> AdaptiveProportionTest>; + +template +class SeedSampler { + public: + // NIST requires 1024 samples at start-up time. This code is structured so + // that the entropy generator is considered to be starting afresh for each + // seed. + static constexpr unsigned kNumSamples = 1024; + + explicit SeedSampler(T &&sub_sampler) + : sub_sampler_(std::forward(sub_sampler)) {} + + bool Next(uint8_t out_seed[48]) { + // HMAC-SHA384 `kNumSamples` samples with an all-zero key: + SHA512_CTX ctx; + SHA384_Init(&ctx); + + uint8_t block[kSHA384Block]; + memset(block, 0x36, sizeof(block)); + SHA384_Update(&ctx, block, sizeof(block)); + + static_assert(kNumSamples % sizeof(block) == 0); + for (unsigned i = 0; i < kNumSamples / sizeof(block); i++) { + for (unsigned j = 0; j < sizeof(block); j++) { + if (!sub_sampler_.Next(&block[j])) { + return false; + } + } + SHA384_Update(&ctx, block, sizeof(block)); + } + + SHA384_Final(out_seed, &ctx); + + SHA384_Init(&ctx); + memset(block, 0x5c, sizeof(block)); + SHA384_Update(&ctx, block, sizeof(block)); + SHA384_Update(&ctx, out_seed, kSHA384DigestLength); + SHA384_Final(out_seed, &ctx); + + return true; + } + + private: + T sub_sampler_; +}; + +template +SeedSampler(U &&sub_sampler) -> SeedSampler>; + +constexpr size_t kMemorySize = 1u << 25; +constexpr size_t kMemoryAccessesPerSample = 16; +constexpr size_t kBitsPerSample = 8; +constexpr uint8_t kMask = (1u << kBitsPerSample) - 1; + +} // namespace + +int GetVersion() { return 20250725; } + +bool GetSeed(uint8_t out[48]) { + auto sampler(SeedSampler(AdaptiveProportionTest(RepetitionCountTest( + MaskSampler(kMask, DeltaSampler(MemoryAccessSampler( + kMemorySize, kMemoryAccessesPerSample))))))); + return sampler.Next(out); +} + +bool GetSamples(uint64_t *out, size_t n) { + auto sampler( + DeltaSampler(MemoryAccessSampler(kMemorySize, kMemoryAccessesPerSample))); + for (size_t i = 0; i < n; i++) { + if (!sampler.Next(&out[i])) { + return false; + } + } + return true; +} + +} // namespace entropy +BSSL_NAMESPACE_END + +#endif // LINUX || MACOS diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/sha512.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/sha512.cc.inc new file mode 100644 index 000000000..14e2975bc --- /dev/null +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/entropy/sha512.cc.inc @@ -0,0 +1,324 @@ +// Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + + +// This is a copy of the SHA-384 code for the purpose of isolating the jitter +// entropy source certification from any changes to the normal implementation. + +namespace bssl::entropy { +namespace { + +constexpr size_t kSHA384Block = 128; +constexpr size_t kSHA384DigestLength = (384 / 8); + +struct SHA512_CTX { + uint64_t h[8]; + uint64_t Nl, Nh; + uint8_t p[kSHA384Block]; + unsigned num, md_len; +}; + +uint64_t CRYPTO_bswap8(uint64_t x) { return __builtin_bswap64(x); } + +uint64_t CRYPTO_load_u64_be(const void *ptr) { + uint64_t ret; + memcpy(&ret, ptr, sizeof(ret)); + return CRYPTO_bswap8(ret); +} + +void CRYPTO_store_u64_be(void *out, uint64_t v) { + v = CRYPTO_bswap8(v); + memcpy(out, &v, sizeof(v)); +} + +uint64_t CRYPTO_rotr_u64(uint64_t value, int shift) { + return (value >> shift) | (value << ((-shift) & 63)); +} + +void sha512_update(SHA512_CTX *c, const void *in_data, size_t len); +void sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha); + +void SHA384_Init(SHA512_CTX *sha) { + sha->h[0] = UINT64_C(0xcbbb9d5dc1059ed8); + sha->h[1] = UINT64_C(0x629a292a367cd507); + sha->h[2] = UINT64_C(0x9159015a3070dd17); + sha->h[3] = UINT64_C(0x152fecd8f70e5939); + sha->h[4] = UINT64_C(0x67332667ffc00b31); + sha->h[5] = UINT64_C(0x8eb44a8768581511); + sha->h[6] = UINT64_C(0xdb0c2e0d64f98fa7); + sha->h[7] = UINT64_C(0x47b5481dbefa4fa4); + + sha->Nl = 0; + sha->Nh = 0; + sha->num = 0; + sha->md_len = kSHA384DigestLength; + return; +} + +void SHA384_Final(uint8_t out[kSHA384DigestLength], SHA512_CTX *sha) { + // This function must be paired with |SHA384_Init|, which sets + // |sha->md_len| to |kSHA384DigestLength|. + sha512_final_impl(out, kSHA384DigestLength, sha); + return; +} + +void SHA384_Update(SHA512_CTX *sha, const void *data, size_t len) { + return sha512_update(sha, data, len); +} + +void sha512_block_data_order(uint64_t state[8], const uint8_t *in, + size_t num_blocks); + +void sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha) { + uint8_t *p = sha->p; + size_t n = sha->num; + + p[n] = 0x80; // There always is a room for one + n++; + if (n > (sizeof(sha->p) - 16)) { + memset(p + n, 0, sizeof(sha->p) - n); + n = 0; + sha512_block_data_order(sha->h, p, 1); + } + + memset(p + n, 0, sizeof(sha->p) - 16 - n); + CRYPTO_store_u64_be(p + sizeof(sha->p) - 16, sha->Nh); + CRYPTO_store_u64_be(p + sizeof(sha->p) - 8, sha->Nl); + + sha512_block_data_order(sha->h, p, 1); + + const size_t out_words = md_len / 8; + for (size_t i = 0; i < out_words; i++) { + CRYPTO_store_u64_be(out, sha->h[i]); + out += 8; + } +} + +const uint64_t K512[80] = { + UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), + UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), + UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), + UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), + UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), + UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), + UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), + UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), + UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), + UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), + UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), + UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), + UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), + UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), + UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), + UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), + UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), + UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), + UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), + UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), + UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), + UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), + UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), + UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), + UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), + UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), + UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), + UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), + UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), + UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), + UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), + UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), + UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), + UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), + UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), + UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), + UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), + UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), + UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), + UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817), +}; + +#define Sigma0(x) \ + (CRYPTO_rotr_u64((x), 28) ^ CRYPTO_rotr_u64((x), 34) ^ \ + CRYPTO_rotr_u64((x), 39)) +#define Sigma1(x) \ + (CRYPTO_rotr_u64((x), 14) ^ CRYPTO_rotr_u64((x), 18) ^ \ + CRYPTO_rotr_u64((x), 41)) +#define sigma0(x) \ + (CRYPTO_rotr_u64((x), 1) ^ CRYPTO_rotr_u64((x), 8) ^ ((x) >> 7)) +#define sigma1(x) \ + (CRYPTO_rotr_u64((x), 19) ^ CRYPTO_rotr_u64((x), 61) ^ ((x) >> 6)) + +#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define ROUND_00_15(i, a, b, c, d, e, f, g, h) \ + do { \ + T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; \ + h = Sigma0(a) + Maj(a, b, c); \ + d += T1; \ + h += T1; \ + } while (0) + +#define ROUND_16_80(i, j, a, b, c, d, e, f, g, h, X) \ + do { \ + s0 = X[(j + 1) & 0x0f]; \ + s0 = sigma0(s0); \ + s1 = X[(j + 14) & 0x0f]; \ + s1 = sigma1(s1); \ + T1 = X[(j) & 0x0f] += s0 + s1 + X[(j + 9) & 0x0f]; \ + ROUND_00_15(i + j, a, b, c, d, e, f, g, h); \ + } while (0) + +void sha512_block_data_order(uint64_t state[8], const uint8_t *in, size_t num) { + uint64_t a, b, c, d, e, f, g, h, s0, s1, T1; + uint64_t X[16]; + int i; + + while (num--) { + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + T1 = X[0] = CRYPTO_load_u64_be(in); + ROUND_00_15(0, a, b, c, d, e, f, g, h); + T1 = X[1] = CRYPTO_load_u64_be(in + 8); + ROUND_00_15(1, h, a, b, c, d, e, f, g); + T1 = X[2] = CRYPTO_load_u64_be(in + 2 * 8); + ROUND_00_15(2, g, h, a, b, c, d, e, f); + T1 = X[3] = CRYPTO_load_u64_be(in + 3 * 8); + ROUND_00_15(3, f, g, h, a, b, c, d, e); + T1 = X[4] = CRYPTO_load_u64_be(in + 4 * 8); + ROUND_00_15(4, e, f, g, h, a, b, c, d); + T1 = X[5] = CRYPTO_load_u64_be(in + 5 * 8); + ROUND_00_15(5, d, e, f, g, h, a, b, c); + T1 = X[6] = CRYPTO_load_u64_be(in + 6 * 8); + ROUND_00_15(6, c, d, e, f, g, h, a, b); + T1 = X[7] = CRYPTO_load_u64_be(in + 7 * 8); + ROUND_00_15(7, b, c, d, e, f, g, h, a); + T1 = X[8] = CRYPTO_load_u64_be(in + 8 * 8); + ROUND_00_15(8, a, b, c, d, e, f, g, h); + T1 = X[9] = CRYPTO_load_u64_be(in + 9 * 8); + ROUND_00_15(9, h, a, b, c, d, e, f, g); + T1 = X[10] = CRYPTO_load_u64_be(in + 10 * 8); + ROUND_00_15(10, g, h, a, b, c, d, e, f); + T1 = X[11] = CRYPTO_load_u64_be(in + 11 * 8); + ROUND_00_15(11, f, g, h, a, b, c, d, e); + T1 = X[12] = CRYPTO_load_u64_be(in + 12 * 8); + ROUND_00_15(12, e, f, g, h, a, b, c, d); + T1 = X[13] = CRYPTO_load_u64_be(in + 13 * 8); + ROUND_00_15(13, d, e, f, g, h, a, b, c); + T1 = X[14] = CRYPTO_load_u64_be(in + 14 * 8); + ROUND_00_15(14, c, d, e, f, g, h, a, b); + T1 = X[15] = CRYPTO_load_u64_be(in + 15 * 8); + ROUND_00_15(15, b, c, d, e, f, g, h, a); + + for (i = 16; i < 80; i += 16) { + ROUND_16_80(i, 0, a, b, c, d, e, f, g, h, X); + ROUND_16_80(i, 1, h, a, b, c, d, e, f, g, X); + ROUND_16_80(i, 2, g, h, a, b, c, d, e, f, X); + ROUND_16_80(i, 3, f, g, h, a, b, c, d, e, X); + ROUND_16_80(i, 4, e, f, g, h, a, b, c, d, X); + ROUND_16_80(i, 5, d, e, f, g, h, a, b, c, X); + ROUND_16_80(i, 6, c, d, e, f, g, h, a, b, X); + ROUND_16_80(i, 7, b, c, d, e, f, g, h, a, X); + ROUND_16_80(i, 8, a, b, c, d, e, f, g, h, X); + ROUND_16_80(i, 9, h, a, b, c, d, e, f, g, X); + ROUND_16_80(i, 10, g, h, a, b, c, d, e, f, X); + ROUND_16_80(i, 11, f, g, h, a, b, c, d, e, X); + ROUND_16_80(i, 12, e, f, g, h, a, b, c, d, X); + ROUND_16_80(i, 13, d, e, f, g, h, a, b, c, X); + ROUND_16_80(i, 14, c, d, e, f, g, h, a, b, X); + ROUND_16_80(i, 15, b, c, d, e, f, g, h, a, X); + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + + in += 16 * 8; + } +} + +#undef Sigma0 +#undef Sigma1 +#undef sigma0 +#undef sigma1 +#undef Ch +#undef Maj +#undef ROUND_00_15 +#undef ROUND_16_80 + +void sha512_update(SHA512_CTX *c, const void *in_data, size_t len) { + uint64_t l; + uint8_t *p = c->p; + const uint8_t *data = reinterpret_cast(in_data); + + if (len == 0) { + return; + } + + l = (c->Nl + (((uint64_t)len) << 3)) & UINT64_C(0xffffffffffffffff); + if (l < c->Nl) { + c->Nh++; + } + if (sizeof(len) >= 8) { + c->Nh += (((uint64_t)len) >> 61); + } + c->Nl = l; + + if (c->num != 0) { + size_t n = sizeof(c->p) - c->num; + + if (len < n) { + memcpy(p + c->num, data, len); + c->num += (unsigned int)len; + return; + } else { + memcpy(p + c->num, data, n), c->num = 0; + len -= n; + data += n; + sha512_block_data_order(c->h, p, 1); + } + } + + if (len >= sizeof(c->p)) { + sha512_block_data_order(c->h, data, len / sizeof(c->p)); + data += len; + len %= sizeof(c->p); + data -= len; + } + + if (len != 0) { + memcpy(p, data, len); + c->num = (int)len; + } + + return; +} + +} // namespace +} // namespace bssl::entropy diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/mldsa/mldsa.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/mldsa/mldsa.cc.inc index 20c99193a..4b1007bba 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/mldsa/mldsa.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/mldsa/mldsa.cc.inc @@ -50,7 +50,6 @@ constexpr uint32_t kPrime = 8380417; constexpr uint32_t kPrimeNegInverse = 4236238847; constexpr int kDroppedBits = 13; constexpr uint32_t kHalfPrime = (kPrime - 1) / 2; -constexpr uint32_t kGamma2 = (kPrime - 1) / 32; // 256^-1 mod kPrime, in Montgomery form. constexpr uint32_t kInverseDegreeMontgomery = 41978; @@ -65,6 +64,8 @@ constexpr size_t public_key_bytes() { return BCM_MLDSA65_PUBLIC_KEY_BYTES; } else if constexpr (K == 8) { return BCM_MLDSA87_PUBLIC_KEY_BYTES; + } else if constexpr (K == 4) { + return BCM_MLDSA44_PUBLIC_KEY_BYTES; } } @@ -74,6 +75,8 @@ constexpr size_t signature_bytes() { return BCM_MLDSA65_SIGNATURE_BYTES; } else if constexpr (K == 8) { return BCM_MLDSA87_SIGNATURE_BYTES; + } else if constexpr (K == 4) { + return BCM_MLDSA44_SIGNATURE_BYTES; } } @@ -83,6 +86,8 @@ constexpr int tau() { return 49; } else if constexpr (K == 8) { return 60; + } else if constexpr (K == 4) { + return 39; } } @@ -92,22 +97,71 @@ constexpr int lambda_bytes() { return 192 / 8; } else if constexpr (K == 8) { return 256 / 8; + } else if constexpr (K == 4) { + return 128 / 8; + } +} + +template +constexpr int gamma1_bits() { + if constexpr (K == 6 || K == 8) { + return 19; + } else if constexpr (K == 4) { + return 17; } } template constexpr int gamma1() { + return 1 << gamma1_bits(); +} + +template +constexpr int scalar_le_gamma1_bytes() { + return ((gamma1_bits() + 1) * kDegree) / 8; +} + +template +constexpr uint32_t w1_coeffs_bits() { if constexpr (K == 6 || K == 8) { - return 1 << 19; + return 4; + } else if constexpr (K == 4) { + return 6; } } +template +constexpr uint32_t w1_scalar_bytes() { + return (w1_coeffs_bits() * kDegree) / 8; +} + +template +constexpr uint32_t w1_bytes() { + return w1_scalar_bytes() * K; +} + +template +constexpr uint32_t prime_minus_one_over_gamma2() { + if constexpr (K == 6 || K == 8) { + return 32; + } else if constexpr (K == 4) { + return 88; + } +} + +template +constexpr uint32_t gamma2() { + return (kPrime - 1) / prime_minus_one_over_gamma2(); +} + template constexpr int beta() { if constexpr (K == 6) { return 196; } else if constexpr (K == 8) { return 120; + } else if constexpr (K == 4) { + return 78; } } @@ -117,6 +171,8 @@ constexpr int omega() { return 55; } else if constexpr (K == 8) { return 75; + } else if constexpr (K == 4) { + return 80; } } @@ -124,7 +180,7 @@ template constexpr int eta() { if constexpr (K == 6) { return 4; - } else if constexpr (K == 8) { + } else if constexpr (K == 8 || K == 4) { return 2; } } @@ -133,7 +189,7 @@ template constexpr int plus_minus_eta_bitlen() { if constexpr (K == 6) { return 4; - } else if constexpr (K == 8) { + } else if constexpr (K == 8 || K == 4) { return 3; } } @@ -433,42 +489,54 @@ void scale_power2_round(uint32_t *out, uint32_t r1) { } // FIPS 204, Algorithm 37 (`HighBits`). +template uint32_t high_bits(uint32_t x) { // Reference description (given 0 <= x < q): // // ``` - // int32_t r0 = x mod+- (2 * kGamma2); + // int32_t r0 = x mod+- (2 * gamma2); // if (x - r0 == q - 1) { // return 0; // } else { - // return (x - r0) / (2 * kGamma2); + // return (x - r0) / (2 * gamma2); // } // ``` // - // Below is the formula taken from the reference implementation. - // - // Here, kGamma2 == 2^18 - 2^8 - // This returns ((ceil(x / 2^7) * (2^10 + 1) + 2^21) / 2^22) mod 2^4 uint32_t r1 = (x + 127) >> 7; - r1 = (r1 * 1025 + (1 << 21)) >> 22; - r1 &= 15; + if constexpr (prime_minus_one_over_gamma2() == 32) { + // Below is the formula taken from the reference implementation. + // + // Here, Gamma2 == 2^18 - 2^8 + // This returns ((ceil(x / 2^7) * (2^10 + 1) + 2^21) / 2^22) mod 2^4 + r1 = (r1 * 1025 + (1 << 21)) >> 22; + r1 &= 15; + } else if constexpr (prime_minus_one_over_gamma2() == 88) { + // 1488/2^24 is close enough to 1/1488 so that r1 becomes x/(2 gamma2) + // rounded down. + r1 = (r1 * 11275 + (1 << 23)) >> 24; + + // For corner-case r1 = (Q-1)/(2 gamma2) = 44, we have to set r1=0. + r1 ^= ((uint32_t)(((int32_t)(43 - r1)) >> 31)) & r1; + } return r1; } // FIPS 204, Algorithm 36 (`Decompose`). +template void decompose(uint32_t *r1, int32_t *r0, uint32_t r) { - *r1 = high_bits(r); + *r1 = high_bits(r); *r0 = r; - *r0 -= *r1 * 2 * (int32_t)kGamma2; + *r0 -= *r1 * 2 * (int32_t)gamma2(); *r0 -= (((int32_t)kHalfPrime - *r0) >> 31) & (int32_t)kPrime; } // FIPS 204, Algorithm 38 (`LowBits`). +template int32_t low_bits(uint32_t x) { uint32_t r1; int32_t r0; - decompose(&r1, &r0, x); + decompose(&r1, &r0, x); return r0; } @@ -480,24 +548,45 @@ int32_t low_bits(uint32_t x) { // // It then computes HighBits (algorithm 37) of z and z+r. But z+r is just w - // cs2, so this takes three arguments and saves an addition. +template int32_t make_hint(uint32_t ct0, uint32_t cs2, uint32_t w) { uint32_t r_plus_z = mod_sub(w, cs2); uint32_t r = reduce_once(r_plus_z + ct0); - return high_bits(r) != high_bits(r_plus_z); + return high_bits(r) != high_bits(r_plus_z); } // FIPS 204, Algorithm 40 (`UseHint`). +template uint32_t use_hint_vartime(uint32_t h, uint32_t r) { uint32_t r1; int32_t r0; - decompose(&r1, &r0, r); + decompose(&r1, &r0, r); if (h) { - if (r0 > 0) { - // m = 16, thus |mod m| in the spec turns into |& 15|. - return (r1 + 1) & 15; + if constexpr (prime_minus_one_over_gamma2() == 32) { + if (r0 > 0) { + // (Q-1)/(2 gamma2) = m = 16, thus |mod m| in the spec turns into |& + // 15|. + return (r1 + 1) & 15; + } else { + return (r1 - 1) & 15; + } } else { - return (r1 - 1) & 15; + // m = 44 + static_assert(prime_minus_one_over_gamma2() == 88); + if (r0 > 0) { + if (r1 == 43) { + return 0; + } else { + return r1 + 1; + } + } else { + if (r1 == 0) { + return 43; + } else { + return r1 - 1; + } + } } } return r1; @@ -515,15 +604,17 @@ void scalar_scale_power2_round(scalar *out, const scalar *in) { } } +template void scalar_high_bits(scalar *out, const scalar *in) { for (int i = 0; i < kDegree; i++) { - out->c[i] = high_bits(in->c[i]); + out->c[i] = high_bits(in->c[i]); } } +template void scalar_low_bits(scalar *out, const scalar *in) { for (int i = 0; i < kDegree; i++) { - out->c[i] = low_bits(in->c[i]); + out->c[i] = low_bits(in->c[i]); } } @@ -541,16 +632,18 @@ void scalar_max_signed(uint32_t *max, const scalar *s) { } } +template void scalar_make_hint(scalar *out, const scalar *ct0, const scalar *cs2, const scalar *w) { for (int i = 0; i < kDegree; i++) { - out->c[i] = make_hint(ct0->c[i], cs2->c[i], w->c[i]); + out->c[i] = make_hint(ct0->c[i], cs2->c[i], w->c[i]); } } +template void scalar_use_hint_vartime(scalar *out, const scalar *h, const scalar *r) { for (int i = 0; i < kDegree; i++) { - out->c[i] = use_hint_vartime(h->c[i], r->c[i]); + out->c[i] = use_hint_vartime(h->c[i], r->c[i]); } } @@ -568,17 +661,17 @@ void vector_scale_power2_round(vector *out, const vector *in) { } } -template -void vector_high_bits(vector *out, const vector *in) { - for (int i = 0; i < X; i++) { - scalar_high_bits(&out->v[i], &in->v[i]); +template +void vector_high_bits(vector *out, const vector *in) { + for (int i = 0; i < K; i++) { + scalar_high_bits(&out->v[i], &in->v[i]); } } -template -void vector_low_bits(vector *out, const vector *in) { - for (int i = 0; i < X; i++) { - scalar_low_bits(&out->v[i], &in->v[i]); +template +void vector_low_bits(vector *out, const vector *in) { + for (int i = 0; i < K; i++) { + scalar_low_bits(&out->v[i], &in->v[i]); } } @@ -612,19 +705,19 @@ size_t vector_count_ones(const vector *a) { return count; } -template -void vector_make_hint(vector *out, const vector *ct0, - const vector *cs2, const vector *w) { - for (int i = 0; i < X; i++) { - scalar_make_hint(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]); +template +void vector_make_hint(vector *out, const vector *ct0, + const vector *cs2, const vector *w) { + for (int i = 0; i < K; i++) { + scalar_make_hint(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]); } } -template -void vector_use_hint_vartime(vector *out, const vector *h, - const vector *r) { - for (int i = 0; i < X; i++) { - scalar_use_hint_vartime(&out->v[i], &h->v[i], &r->v[i]); +template +void vector_use_hint_vartime(vector *out, const vector *h, + const vector *r) { + for (int i = 0; i < K; i++) { + scalar_use_hint_vartime(&out->v[i], &h->v[i], &r->v[i]); } } @@ -643,6 +736,25 @@ static void scalar_encode_4(uint8_t out[128], const scalar *s) { } } +// FIPS 204, Algorithm 16 (`SimpleBitPack`). Specialized to bitlen(b) = 6. +void scalar_encode_6(uint8_t out[192], const scalar *s) { + // Every four elements lands on a byte boundary. + static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); + for (int i = 0; i < kDegree / 4; i++) { + uint32_t a = s->c[4 * i]; + uint32_t b = s->c[4 * i + 1]; + uint32_t c = s->c[4 * i + 2]; + uint32_t d = s->c[4 * i + 3]; + declassify_assert(a < 64); + declassify_assert(b < 64); + declassify_assert(c < 64); + declassify_assert(d < 64); + out[3 * i] = a | (b << 6); + out[3 * i + 1] = (b >> 2) | (c << 4); + out[3 * i + 2] = (c >> 4) | (d << 2); + } +} + // FIPS 204, Algorithm 16 (`SimpleBitPack`). Specialized to bitlen(b) = 10. void scalar_encode_10(uint8_t out[320], const scalar *s) { // Every four elements lands on a byte boundary. @@ -730,10 +842,10 @@ void scalar_encode_signed_13_12(uint8_t out[416], const scalar *s) { e |= g << 14; e |= h << 27; h >>= 5; - OPENSSL_memcpy(&out[13 * i], &a, sizeof(a)); - OPENSSL_memcpy(&out[13 * i + 4], &c, sizeof(c)); - OPENSSL_memcpy(&out[13 * i + 8], &e, sizeof(e)); - OPENSSL_memcpy(&out[13 * i + 12], &h, 1); + CRYPTO_store_u32_le(&out[13 * i], a); + CRYPTO_store_u32_le(&out[13 * i + 4], c); + CRYPTO_store_u32_le(&out[13 * i + 8], e); + out[13 * i + 12] = static_cast(h); } } @@ -757,9 +869,35 @@ void scalar_encode_signed_20_19(uint8_t out[640], const scalar *s) { b |= c << 8; b |= d << 28; d >>= 4; - OPENSSL_memcpy(&out[10 * i], &a, sizeof(a)); - OPENSSL_memcpy(&out[10 * i + 4], &b, sizeof(b)); - OPENSSL_memcpy(&out[10 * i + 8], &d, 2); + CRYPTO_store_u32_le(&out[10 * i], a); + CRYPTO_store_u32_le(&out[10 * i + 4], b); + CRYPTO_store_u16_le(&out[10 * i + 8], static_cast(d)); + } +} + +// FIPS 204, Algorithm 17 (`BitPack`). Specialized to bitlen(a+b) = 18 and b = +// 2^17. +void scalar_encode_signed_18_17(uint8_t out[576], const scalar *s) { + static const uint32_t kMax = 1u << 17; + static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); + for (int i = 0; i < kDegree / 4; i++) { + uint32_t a = mod_sub(kMax, s->c[4 * i]); + uint32_t b = mod_sub(kMax, s->c[4 * i + 1]); + uint32_t c = mod_sub(kMax, s->c[4 * i + 2]); + uint32_t d = mod_sub(kMax, s->c[4 * i + 3]); + declassify_assert(a < (1u << 18)); + declassify_assert(b < (1u << 18)); + declassify_assert(c < (1u << 18)); + declassify_assert(d < (1u << 18)); + out[9 * i] = (uint8_t)a; + out[9 * i + 1] = (uint8_t)(a >> 8); + out[9 * i + 2] = (uint8_t)(a >> 16) | (uint8_t)(b << 2); + out[9 * i + 3] = (uint8_t)(b >> 6); + out[9 * i + 4] = (uint8_t)(b >> 14) | (uint8_t)(c << 4); + out[9 * i + 5] = (uint8_t)(c >> 4); + out[9 * i + 6] = (uint8_t)(c >> 12) | (uint8_t)(d << 6); + out[9 * i + 7] = (uint8_t)(d >> 2); + out[9 * i + 8] = (uint8_t)(d >> 10); } } @@ -775,6 +913,9 @@ void scalar_encode_signed(uint8_t *out, const scalar *s, int bits, } else if (bits == 20) { assert(max == 1u << 19); scalar_encode_signed_20_19(out, s); + } else if (bits == 18) { + assert(max == 1u << 17); + scalar_encode_signed_18_17(out, s); } else { assert(bits == 13); assert(max == 1u << 12); @@ -784,10 +925,9 @@ void scalar_encode_signed(uint8_t *out, const scalar *s, int bits, // FIPS 204, Algorithm 18 (`SimpleBitUnpack`). Specialized for bitlen(b) == 10. void scalar_decode_10(scalar *out, const uint8_t in[320]) { - uint32_t v; static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); for (int i = 0; i < kDegree / 4; i++) { - OPENSSL_memcpy(&v, &in[5 * i], sizeof(v)); + uint32_t v = CRYPTO_load_u32_le(&in[5 * i]); out->c[4 * i] = v & 0x3ff; out->c[4 * i + 1] = (v >> 10) & 0x3ff; out->c[4 * i + 2] = (v >> 20) & 0x3ff; @@ -798,10 +938,9 @@ void scalar_decode_10(scalar *out, const uint8_t in[320]) { // FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 4 and b = // 4. int scalar_decode_signed_4_4(scalar *out, const uint8_t in[128]) { - uint32_t v; static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8"); for (int i = 0; i < kDegree / 8; i++) { - OPENSSL_memcpy(&v, &in[4 * i], sizeof(v)); + uint32_t v = CRYPTO_load_u32_le(&in[4 * i]); // None of the nibbles may be >= 9. So if the MSB of any nibble is set, none // of the other bits may be set. First, select all the MSBs. const uint32_t msbs = v & 0x88888888u; @@ -865,14 +1004,12 @@ void scalar_decode_signed_13_12(scalar *out, const uint8_t in[416]) { static const uint32_t k13Bits = (1u << 13) - 1; static const uint32_t k7Bits = (1u << 7) - 1; - uint32_t a, b, c; - uint8_t d; static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8"); for (int i = 0; i < kDegree / 8; i++) { - OPENSSL_memcpy(&a, &in[13 * i], sizeof(a)); - OPENSSL_memcpy(&b, &in[13 * i + 4], sizeof(b)); - OPENSSL_memcpy(&c, &in[13 * i + 8], sizeof(c)); - d = in[13 * i + 12]; + uint32_t a = CRYPTO_load_u32_le(&in[13 * i]); + uint32_t b = CRYPTO_load_u32_le(&in[13 * i + 4]); + uint32_t c = CRYPTO_load_u32_le(&in[13 * i + 8]); + uint8_t d = in[13 * i + 12]; // It's not possible for a 13-bit number to be out of range when the max is // 2^12. @@ -887,19 +1024,43 @@ void scalar_decode_signed_13_12(scalar *out, const uint8_t in[416]) { } } +// FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 18 and b = +// 2^17. +void scalar_decode_signed_18_17(scalar *out, const uint8_t in[576]) { + static const uint32_t kMax = 1u << 17; + + static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); + for (int i = 0; i < kDegree / 4; i++) { + uint32_t a = uint32_t{in[9 * i]} | (uint32_t{in[9 * i + 1]} << 8) | + ((uint32_t{in[9 * i + 2]} & 0x3) << 16); + uint32_t b = (uint32_t{in[9 * i + 2]} >> 2) | + (uint32_t{in[9 * i + 3]} << 6) | + ((uint32_t{in[9 * i + 4]} & 0xf) << 14); + uint32_t c = (uint32_t{in[9 * i + 4]} >> 4) | + (uint32_t{in[9 * i + 5]} << 4) | + ((uint32_t{in[9 * i + 6]} & 0x3f) << 12); + uint32_t d = (uint32_t{in[9 * i + 6]} >> 6) | + (uint32_t{in[9 * i + 7]} << 2) | + (uint32_t{in[9 * i + 8]} << 10); + + out->c[i * 4] = mod_sub(kMax, a); + out->c[i * 4 + 1] = mod_sub(kMax, b); + out->c[i * 4 + 2] = mod_sub(kMax, c); + out->c[i * 4 + 3] = mod_sub(kMax, d); + } +} + // FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 20 and b = // 2^19. void scalar_decode_signed_20_19(scalar *out, const uint8_t in[640]) { static const uint32_t kMax = 1u << 19; static const uint32_t k20Bits = (1u << 20) - 1; - uint32_t a, b; - uint16_t c; static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4"); for (int i = 0; i < kDegree / 4; i++) { - OPENSSL_memcpy(&a, &in[10 * i], sizeof(a)); - OPENSSL_memcpy(&b, &in[10 * i + 4], sizeof(b)); - OPENSSL_memcpy(&c, &in[10 * i + 8], sizeof(c)); + uint32_t a = CRYPTO_load_u32_le(&in[10 * i]); + uint32_t b = CRYPTO_load_u32_le(&in[10 * i + 4]); + uint16_t c = CRYPTO_load_u16_le(&in[10 * i + 8]); // It's not possible for a 20-bit number to be out of range when the max is // 2^19. @@ -923,6 +1084,10 @@ int scalar_decode_signed(scalar *out, const uint8_t *in, int bits, assert(max == (1u << 12)); scalar_decode_signed_13_12(out, in); return 1; + } else if (bits == 18) { + assert(max == (1u << 17)); + scalar_decode_signed_18_17(out, in); + return 1; } else if (bits == 20) { assert(max == (1u << 19)); scalar_decode_signed_20_19(out, in); @@ -1016,13 +1181,14 @@ void scalar_uniform(scalar *out, const uint8_t derived_seed[kSigmaBytes + 2]) { } // FIPS 204, Algorithm 34 (`ExpandMask`), but just a single step. +template void scalar_sample_mask(scalar *out, const uint8_t derived_seed[kRhoPrimeBytes + 2]) { - uint8_t buf[640]; + uint8_t buf[scalar_le_gamma1_bytes()]; BORINGSSL_keccak(buf, sizeof(buf), derived_seed, kRhoPrimeBytes + 2, boringssl_shake256); - scalar_decode_signed_20_19(out, buf); + scalar_decode_signed(out, buf, gamma1_bits() + 1, gamma1()); } // FIPS 204, Algorithm 29 (`SampleInBall`). @@ -1108,7 +1274,7 @@ void vector_expand_short(vector *s1, vector *s2, } // FIPS 204, Algorithm 34 (`ExpandMask`). -template +template void vector_expand_mask(vector *out, const uint8_t seed[kRhoPrimeBytes], size_t kappa) { assert(kappa + L <= 0x10000); @@ -1119,7 +1285,7 @@ void vector_expand_mask(vector *out, const uint8_t seed[kRhoPrimeBytes], size_t index = kappa + i; derived_seed[kRhoPrimeBytes] = index & 0xFF; derived_seed[kRhoPrimeBytes + 1] = (index >> 8) & 0xFF; - scalar_sample_mask(&out->v[i], derived_seed); + scalar_sample_mask(&out->v[i], derived_seed); } } @@ -1136,6 +1302,10 @@ void vector_encode(uint8_t *out, const vector *a, int bits) { for (int i = 0; i < K; i++) { scalar_encode_4(out + i * bits * kDegree / 8, &a->v[i]); } + } else if (bits == 6) { + for (int i = 0; i < K; i++) { + scalar_encode_6(out + i * bits * kDegree / 8, &a->v[i]); + } } else { assert(bits == 10); for (int i = 0; i < K; i++) { @@ -1179,8 +1349,8 @@ int vector_decode_signed(vector *out, const uint8_t *in, int bits, // FIPS 204, Algorithm 28 (`w1Encode`). template -void w1_encode(uint8_t out[128 * K], const vector *w1) { - vector_encode(out, w1, 4); +void w1_encode(uint8_t out[w1_bytes()], const vector *w1) { + vector_encode(out, w1, w1_coeffs_bits()); } // FIPS 204, Algorithm 20 (`HintBitPack`). @@ -1364,10 +1534,11 @@ int mldsa_marshal_signature(CBB *out, const struct signature *sign) { } uint8_t *vectorl_output; - if (!CBB_add_space(out, &vectorl_output, 640 * L)) { + if (!CBB_add_space(out, &vectorl_output, scalar_le_gamma1_bytes() * L)) { return 0; } - vector_encode_signed(vectorl_output, &sign->z, 20, 1 << 19); + vector_encode_signed(vectorl_output, &sign->z, gamma1_bits() + 1, + gamma1()); uint8_t *hint_output; if (!CBB_add_space(out, &hint_output, omega() + K)) { @@ -1384,9 +1555,10 @@ int mldsa_parse_signature(struct signature *sign, CBS *in) { CBS z_bytes; CBS hint_bytes; if (!CBS_copy_bytes(in, sign->c_tilde, sizeof(sign->c_tilde)) || - !CBS_get_bytes(in, &z_bytes, 640 * L) || - // Note: Decoding 20 bits into (-2^19, 2^19] cannot fail. - !vector_decode_signed(&sign->z, CBS_data(&z_bytes), 20, 1 << 19) || + !CBS_get_bytes(in, &z_bytes, scalar_le_gamma1_bytes() * L) || + // Note: Decoding b+1 bits into (-2^b, 2^b] cannot fail. + !vector_decode_signed(&sign->z, CBS_data(&z_bytes), gamma1_bits() + 1, + gamma1()) || !CBS_get_bytes(in, &hint_bytes, omega() + K) || !hint_bit_unpack(&sign->h, CBS_data(&hint_bytes))) { return 0; @@ -1561,7 +1733,7 @@ int mldsa_sign_mu( // kappa must not exceed 2**16/L = 13107. But the probability of it // exceeding even 1000 iterations is vanishingly small. for (size_t kappa = 0;; kappa += L) { - vector_expand_mask(&values->y, rho_prime, kappa); + vector_expand_mask(&values->y, rho_prime, kappa); vector *y_ntt = &values->cs1; OPENSSL_memcpy(y_ntt, &values->y, sizeof(*y_ntt)); @@ -1571,12 +1743,12 @@ int mldsa_sign_mu( vector_inverse_ntt(&values->w); vector_high_bits(&values->w1, &values->w); - uint8_t w1_encoded[128 * K]; + uint8_t w1_encoded[w1_bytes()]; w1_encode(w1_encoded, &values->w1); BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); BORINGSSL_keccak_absorb(&keccak_ctx, mu, kMuBytes); - BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); + BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, w1_bytes()); BORINGSSL_keccak_squeeze(&keccak_ctx, values->sign.c_tilde, 2 * lambda_bytes()); @@ -1609,7 +1781,7 @@ int mldsa_sign_mu( uint32_t r0_max = vector_max_signed(r0); if (constant_time_declassify_w( constant_time_ge_w(z_max, gamma1() - beta()) | - constant_time_ge_w(r0_max, kGamma2 - beta()))) { + constant_time_ge_w(r0_max, gamma2() - beta()))) { #if defined(BORINGSSL_FIPS_BREAK_TESTS) // In order to show that our self-tests trigger both restart cases in // this loop, printf-logging is added when built in break-test mode. @@ -1626,7 +1798,7 @@ int mldsa_sign_mu( // See above. uint32_t ct0_max = vector_max(ct0); size_t h_ones = vector_count_ones(&values->sign.h); - if (constant_time_declassify_w(constant_time_ge_w(ct0_max, kGamma2) | + if (constant_time_declassify_w(constant_time_ge_w(ct0_max, gamma2()) | constant_time_lt_w(omega(), h_ones))) { #if defined(BORINGSSL_FIPS_BREAK_TESTS) // In order to show that our self-tests trigger both restart cases in @@ -1778,13 +1950,13 @@ int mldsa_verify_internal_no_self_test( vector_inverse_ntt(w1); vector_use_hint_vartime(w1, &values->sign.h, w1); - uint8_t w1_encoded[128 * K]; + uint8_t w1_encoded[w1_bytes()]; w1_encode(w1_encoded, w1); uint8_t c_tilde[2 * lambda_bytes()]; BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); BORINGSSL_keccak_absorb(&keccak_ctx, mu, kMuBytes); - BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); + BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, w1_bytes()); BORINGSSL_keccak_squeeze(&keccak_ctx, c_tilde, 2 * lambda_bytes()); uint32_t z_max = vector_max(&values->sign.z); @@ -1871,6 +2043,39 @@ struct prehash_context *prehash_context_from_external_87( return reinterpret_cast(external); } +struct private_key<4, 4> *private_key_from_external_44( + const struct BCM_mldsa44_private_key *external) { + static_assert(sizeof(struct BCM_mldsa44_private_key) == + sizeof(struct private_key<4, 4>), + "MLDSA44 private key size incorrect"); + static_assert(alignof(struct BCM_mldsa44_private_key) == + alignof(struct private_key<4, 4>), + "MLDSA44 private key alignment incorrect"); + return (struct private_key<4, 4> *)external; +} + +struct public_key<4> *public_key_from_external_44( + const struct BCM_mldsa44_public_key *external) { + static_assert( + sizeof(struct BCM_mldsa44_public_key) == sizeof(struct public_key<4>), + "MLDSA44 public key size incorrect"); + static_assert( + alignof(struct BCM_mldsa44_public_key) == alignof(struct public_key<4>), + "MLDSA44 public key alignment incorrect"); + return (struct public_key<4> *)external; +} + +struct prehash_context *prehash_context_from_external_44( + struct BCM_mldsa44_prehash *external) { + static_assert( + sizeof(struct BCM_mldsa44_prehash) == sizeof(struct prehash_context), + "MLDSA pre-hash context size incorrect"); + static_assert( + alignof(struct BCM_mldsa44_prehash) == alignof(struct prehash_context), + "MLDSA pre-hash context alignment incorrect"); + return reinterpret_cast(external); +} + namespace fips { #include "fips_known_values.inc" @@ -2442,6 +2647,209 @@ bcm_status BCM_mldsa87_marshal_public_key( out, mldsa::public_key_from_external_87(public_key))); } + +// ML-DSA-44 specific wrappers. + +bcm_status BCM_mldsa44_parse_public_key( + struct BCM_mldsa44_public_key *public_key, CBS *in) { + return bcm_as_approved_status(mldsa_parse_public_key( + mldsa::public_key_from_external_44(public_key), in)); +} + +bcm_status BCM_mldsa44_marshal_private_key( + CBB *out, const struct BCM_mldsa44_private_key *private_key) { + return bcm_as_approved_status(mldsa_marshal_private_key( + out, mldsa::private_key_from_external_44(private_key))); +} + +bcm_status BCM_mldsa44_parse_private_key( + struct BCM_mldsa44_private_key *private_key, CBS *in) { + return bcm_as_approved_status( + mldsa_parse_private_key(mldsa::private_key_from_external_44(private_key), + in) && + CBS_len(in) == 0); +} + +bcm_status BCM_mldsa44_check_key_fips( + struct BCM_mldsa44_private_key *private_key) { + return bcm_as_approved_status( + mldsa::fips::check_key(mldsa::private_key_from_external_44(private_key))); +} + +// Calls |MLDSA_generate_key_external_entropy| with random bytes from +// |BCM_rand_bytes|. +bcm_status BCM_mldsa44_generate_key( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key) { + BCM_rand_bytes(out_seed, BCM_MLDSA_SEED_BYTES); + return BCM_mldsa44_generate_key_external_entropy(out_encoded_public_key, + out_private_key, out_seed); +} + +bcm_status BCM_mldsa44_private_key_from_seed( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]) { + uint8_t public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES]; + return BCM_mldsa44_generate_key_external_entropy(public_key, out_private_key, + seed); +} + +bcm_status BCM_mldsa44_generate_key_external_entropy( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) { + return bcm_as_not_approved_status(mldsa_generate_key_external_entropy( + out_encoded_public_key, + mldsa::private_key_from_external_44(out_private_key), entropy)); +} + +bcm_status BCM_mldsa44_generate_key_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[BCM_MLDSA_SEED_BYTES], + struct BCM_mldsa44_private_key *out_private_key) { + if (out_encoded_public_key == nullptr || out_private_key == nullptr) { + return bcm_status::failure; + } + if (BCM_mldsa44_generate_key(out_encoded_public_key, out_seed, + out_private_key) == bcm_status::failure) { + return bcm_status::failure; + } + return BCM_mldsa44_check_key_fips(out_private_key); +} + +bcm_status BCM_mldsa44_generate_key_external_entropy_fips( + uint8_t out_encoded_public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES], + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) { + if (out_encoded_public_key == nullptr || out_private_key == nullptr) { + return bcm_status::failure; + } + if (BCM_mldsa44_generate_key_external_entropy(out_encoded_public_key, + out_private_key, entropy) == + bcm_status::failure) { + return bcm_status::failure; + } + return BCM_mldsa44_check_key_fips(out_private_key); +} + +bcm_status BCM_mldsa44_private_key_from_seed_fips( + struct BCM_mldsa44_private_key *out_private_key, + const uint8_t seed[BCM_MLDSA_SEED_BYTES]) { + uint8_t public_key[BCM_MLDSA44_PUBLIC_KEY_BYTES]; + if (BCM_mldsa44_generate_key_external_entropy(public_key, out_private_key, + seed) == bcm_status::failure) { + return bcm_status::failure; + } + return BCM_mldsa44_check_key_fips(out_private_key); +} + +bcm_status BCM_mldsa44_public_from_private( + struct BCM_mldsa44_public_key *out_public_key, + const struct BCM_mldsa44_private_key *private_key) { + return bcm_as_approved_status(mldsa_public_from_private( + mldsa::public_key_from_external_44(out_public_key), + mldsa::private_key_from_external_44(private_key))); +} + +bcm_status BCM_mldsa44_sign_internal( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context_prefix, size_t context_prefix_len, + const uint8_t *context, size_t context_len, + const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) { + return bcm_as_approved_status(mldsa_sign_internal( + out_encoded_signature, mldsa::private_key_from_external_44(private_key), + msg, msg_len, context_prefix, context_prefix_len, context, context_len, + randomizer)); +} + +// ML-DSA signature in randomized mode, filling the random bytes with +// |BCM_rand_bytes|. +bcm_status BCM_mldsa44_sign( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context, size_t context_len) { + BSSL_CHECK(context_len <= 255); + uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]; + BCM_rand_bytes(randomizer, sizeof(randomizer)); + + const uint8_t context_prefix[2] = {0, static_cast(context_len)}; + return BCM_mldsa44_sign_internal( + out_encoded_signature, private_key, msg, msg_len, context_prefix, + sizeof(context_prefix), context, context_len, randomizer); +} + +// ML-DSA pre-hashed API: initializing a pre-hashing context. +void BCM_mldsa44_prehash_init(struct BCM_mldsa44_prehash *out_prehash_ctx, + const struct BCM_mldsa44_public_key *public_key, + const uint8_t *context, size_t context_len) { + BSSL_CHECK(context_len <= 255); + + const uint8_t context_prefix[2] = {0, static_cast(context_len)}; + mldsa_prehash_init(mldsa::prehash_context_from_external_44(out_prehash_ctx), + mldsa::public_key_from_external_44(public_key), + context_prefix, sizeof(context_prefix), context, + context_len); +} + +// ML-DSA pre-hashed API: updating a pre-hashing context with a message chunk. +void BCM_mldsa44_prehash_update(struct BCM_mldsa44_prehash *inout_prehash_ctx, + const uint8_t *msg, size_t msg_len) { + mldsa_prehash_update( + mldsa::prehash_context_from_external_44(inout_prehash_ctx), msg, msg_len); +} + +// ML-DSA pre-hashed API: obtaining a message representative to sign. +void BCM_mldsa44_prehash_finalize( + uint8_t out_msg_rep[BCM_MLDSA_MU_BYTES], + struct BCM_mldsa44_prehash *inout_prehash_ctx) { + mldsa_prehash_finalize( + out_msg_rep, mldsa::prehash_context_from_external_44(inout_prehash_ctx)); +} + +// ML-DSA pre-hashed API: signing a message representative. +bcm_status BCM_mldsa44_sign_message_representative( + uint8_t out_encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const struct BCM_mldsa44_private_key *private_key, + const uint8_t msg_rep[BCM_MLDSA_MU_BYTES]) { + uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]; + BCM_rand_bytes(randomizer, sizeof(randomizer)); + CONSTTIME_SECRET(randomizer, sizeof(randomizer)); + + return bcm_as_approved_status(mldsa_sign_mu( + out_encoded_signature, mldsa::private_key_from_external_44(private_key), + msg_rep, randomizer)); +} + +// FIPS 204, Algorithm 3 (`ML-DSA.Verify`). +bcm_status BCM_mldsa44_verify(const struct BCM_mldsa44_public_key *public_key, + const uint8_t *signature, const uint8_t *msg, + size_t msg_len, const uint8_t *context, + size_t context_len) { + BSSL_CHECK(context_len <= 255); + const uint8_t context_prefix[2] = {0, static_cast(context_len)}; + return BCM_mldsa44_verify_internal(public_key, signature, msg, msg_len, + context_prefix, sizeof(context_prefix), + context, context_len); +} + +bcm_status BCM_mldsa44_verify_internal( + const struct BCM_mldsa44_public_key *public_key, + const uint8_t encoded_signature[BCM_MLDSA44_SIGNATURE_BYTES], + const uint8_t *msg, size_t msg_len, const uint8_t *context_prefix, + size_t context_prefix_len, const uint8_t *context, size_t context_len) { + return bcm_as_approved_status(mldsa::mldsa_verify_internal<4, 4>( + mldsa::public_key_from_external_44(public_key), encoded_signature, msg, + msg_len, context_prefix, context_prefix_len, context, context_len)); +} + +bcm_status BCM_mldsa44_marshal_public_key( + CBB *out, const struct BCM_mldsa44_public_key *public_key) { + return bcm_as_approved_status(mldsa_marshal_public_key( + out, mldsa::public_key_from_external_44(public_key))); +} + int boringssl_self_test_mldsa() { return mldsa::fips::keygen_self_test() && mldsa::fips::sign_self_test() && mldsa::fips::verify_self_test(); diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/ctrdrbg.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/ctrdrbg.cc.inc index 72590382f..231c0bb46 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/ctrdrbg.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/ctrdrbg.cc.inc @@ -17,6 +17,7 @@ #include #include +#include #include "../aes/internal.h" #include "../service_indicator/internal.h" @@ -26,8 +27,122 @@ // Section references in this file refer to SP 800-90Ar1: // http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf -// See table 3. -static const uint64_t kMaxReseedCount = UINT64_C(1) << 48; +// Also see table 3. +constexpr uint64_t kMaxReseedCount = UINT64_C(1) << 48; + +// Implements the BCC function as described in Section 10.3.3. +static void bcc(uint8_t out[AES_BLOCK_SIZE], const AES_KEY *aes_key, + const uint8_t *data, size_t data_len) { + // 1. chaining_value = 0^outlen. + uint8_t *chaining_value = out; + OPENSSL_memset(chaining_value, 0, AES_BLOCK_SIZE); + + // 2. n = len (data)/outlen. + BSSL_CHECK(data_len % AES_BLOCK_SIZE == 0); + const size_t n = data_len / AES_BLOCK_SIZE; + + for (size_t i = 0; i < n; i++) { + const uint8_t *block = data + (i * AES_BLOCK_SIZE); + uint8_t input_block[AES_BLOCK_SIZE]; + + // 4.1: input_block = chaining_value ⊕ block_i. + CRYPTO_xor16(input_block, chaining_value, block); + + // 4.2: chaining_value = Block_Encrypt (Key, input_block). + BCM_aes_encrypt(input_block, chaining_value, aes_key); + } + + // 5. output_block = chaining_value. +} + +// Implements the derivation function as described in Section 10.3.2. +static int block_cipher_df(uint8_t *out, size_t out_len, const uint8_t *input, + size_t input_len) { + // Constants for AES-256 + constexpr size_t kAESKeyLen = 32; + constexpr size_t kAESOutLen = AES_BLOCK_SIZE; + constexpr size_t kMaxNumBits = 512; + + if (out_len > kMaxNumBits / 8 || input_len > (1u << 30)) { + return 0; + } + + // 4. S = L || N || input_string || 0x80. + const size_t s_rawlen = sizeof(uint32_t) + sizeof(uint32_t) + input_len + 1; + // S is padded up to a block size. + const size_t s_len = (s_rawlen + kAESOutLen - 1) & ~(kAESOutLen - 1); + uint8_t iv_plus_s[/* space used below */ kAESOutLen + 4 + 4 + + CTR_DRBG_MAX_ENTROPY_LEN + CTR_DRBG_NONCE_LEN + + CTR_DRBG_SEED_LEN + 1 + + /* padding */ 7]; + if (kAESOutLen + s_len > sizeof(iv_plus_s)) { + return 0; + } + OPENSSL_memset(iv_plus_s, 0, sizeof(iv_plus_s)); + uint8_t *s_ptr = iv_plus_s + kAESOutLen; + // 2. L = len (input_string)/8. + CRYPTO_store_u32_be(s_ptr, (uint32_t)input_len); + s_ptr += sizeof(uint32_t); + // 3. N = number_of_bits_to_return/8. + CRYPTO_store_u32_be(s_ptr, (uint32_t)out_len); + s_ptr += sizeof(uint32_t); + OPENSSL_memcpy(s_ptr, input, input_len); + s_ptr += input_len; + *s_ptr = 0x80; + + uint8_t temp[kAESKeyLen + kAESOutLen]; + size_t temp_len = 0; + + // 8. K = leftmost (0x00010203...1D1E1F, keylen). + static const uint8_t kInitialKey[kAESKeyLen] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; + AES_KEY aes_key; + bcm_status status = + BCM_aes_set_encrypt_key(kInitialKey, 8 * sizeof(kInitialKey), &aes_key); + BSSL_CHECK(status != bcm_status::failure); + + // 7. i = 0. + uint32_t i = 0; + while (temp_len < sizeof(temp)) { + // 9.1 IV = i || 0^(outlen - len(i)). + CRYPTO_store_u32_be(iv_plus_s, i); + + // 9.2 temp = temp || BCC (K, (IV || S)). + bcc(temp + temp_len, &aes_key, iv_plus_s, kAESOutLen + s_len); + temp_len += kAESOutLen; + + // 9.3 i = i + 1. + i++; + } + + // 10. K = leftmost (temp, keylen). + uint8_t *const k = temp; + + // 11. X = select (temp, keylen+1, keylen+outlen). + uint8_t *const x = temp + kAESKeyLen; + + // 12. temp = the Null string. + temp_len = 0; + + // Create an AES key schedule for the final encryption steps. + status = BCM_aes_set_encrypt_key(k, kAESKeyLen * 8, &aes_key); + BSSL_CHECK(status != bcm_status::failure); + + // 13. While len (temp) < number_of_bits_to_return, do: + while (temp_len < out_len) { + // 13.1 X = Block_Encrypt (K, X). + BCM_aes_encrypt(x, x, &aes_key); + + // 13.2 temp = temp || X. + size_t to_copy = std::min(kAESOutLen, out_len - temp_len); + OPENSSL_memcpy(out + temp_len, x, to_copy); + temp_len += to_copy; + } + + return 1; +} CTR_DRBG_STATE *CTR_DRBG_new(const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], const uint8_t *personalization, @@ -35,7 +150,24 @@ CTR_DRBG_STATE *CTR_DRBG_new(const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], CTR_DRBG_STATE *drbg = reinterpret_cast( OPENSSL_malloc(sizeof(CTR_DRBG_STATE))); if (drbg == NULL || - !CTR_DRBG_init(drbg, entropy, personalization, personalization_len)) { + !CTR_DRBG_init(drbg, /*df=*/false, entropy, CTR_DRBG_ENTROPY_LEN, + /*nonce=*/nullptr, personalization, personalization_len)) { + CTR_DRBG_free(drbg); + return NULL; + } + + return drbg; +} + +CTR_DRBG_STATE *CTR_DRBG_new_df(const uint8_t *entropy, size_t entropy_len, + const uint8_t nonce[CTR_DRBG_NONCE_LEN], + const uint8_t *personalization, + size_t personalization_len) { + CTR_DRBG_STATE *drbg = reinterpret_cast( + OPENSSL_malloc(sizeof(CTR_DRBG_STATE))); + if (drbg == NULL || + !CTR_DRBG_init(drbg, /*df=*/true, entropy, entropy_len, nonce, + personalization, personalization_len)) { CTR_DRBG_free(drbg); return NULL; } @@ -45,26 +177,45 @@ CTR_DRBG_STATE *CTR_DRBG_new(const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], void CTR_DRBG_free(CTR_DRBG_STATE *state) { OPENSSL_free(state); } -int CTR_DRBG_init(CTR_DRBG_STATE *drbg, - const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], +int CTR_DRBG_init(CTR_DRBG_STATE *drbg, int df, const uint8_t *entropy, + size_t entropy_len, const uint8_t nonce[CTR_DRBG_NONCE_LEN], const uint8_t *personalization, size_t personalization_len) { - // Section 10.2.1.3.1 - if (personalization_len > CTR_DRBG_ENTROPY_LEN) { + // Section 10.2.1.3.1 and 10.2.1.3.2 + if (personalization_len > CTR_DRBG_SEED_LEN || + (!df && entropy_len != CTR_DRBG_ENTROPY_LEN) || + (df && (entropy_len < CTR_DRBG_MIN_ENTROPY_LEN || + entropy_len > CTR_DRBG_MAX_ENTROPY_LEN)) || // + (df != (nonce != nullptr))) { return 0; } - uint8_t seed_material[CTR_DRBG_ENTROPY_LEN]; - OPENSSL_memcpy(seed_material, entropy, CTR_DRBG_ENTROPY_LEN); - - for (size_t i = 0; i < personalization_len; i++) { - seed_material[i] ^= personalization[i]; + uint8_t seed_material[CTR_DRBG_SEED_LEN]; + if (df) { + uint8_t pre_seed_material[CTR_DRBG_MAX_ENTROPY_LEN + CTR_DRBG_NONCE_LEN + + CTR_DRBG_SEED_LEN]; + OPENSSL_memcpy(pre_seed_material, entropy, entropy_len); + OPENSSL_memcpy(pre_seed_material + entropy_len, nonce, CTR_DRBG_NONCE_LEN); + OPENSSL_memcpy(pre_seed_material + entropy_len + CTR_DRBG_NONCE_LEN, + personalization, personalization_len); + const size_t pre_seed_material_length = + entropy_len + CTR_DRBG_NONCE_LEN + personalization_len; + + if (!block_cipher_df(seed_material, sizeof(seed_material), + pre_seed_material, pre_seed_material_length)) { + return 0; + } + } else { + OPENSSL_memcpy(seed_material, entropy, CTR_DRBG_ENTROPY_LEN); + for (size_t i = 0; i < personalization_len; i++) { + seed_material[i] ^= personalization[i]; + } } // Section 10.2.1.2 // kInitMask is the result of encrypting blocks with big-endian value 1, 2 // and 3 with the all-zero AES-256 key. - static const uint8_t kInitMask[CTR_DRBG_ENTROPY_LEN] = { + static const uint8_t kInitMask[CTR_DRBG_SEED_LEN] = { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b, 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18, 0x72, 0x60, 0x03, 0xca, @@ -75,6 +226,7 @@ int CTR_DRBG_init(CTR_DRBG_STATE *drbg, seed_material[i] ^= kInitMask[i]; } + drbg->df = df; drbg->ctr = aes_ctr_set_key(&drbg->ks, NULL, &drbg->block, seed_material, 32); OPENSSL_memcpy(drbg->counter, seed_material + 32, 16); drbg->reseed_counter = 1; @@ -82,7 +234,7 @@ int CTR_DRBG_init(CTR_DRBG_STATE *drbg, return 1; } -static_assert(CTR_DRBG_ENTROPY_LEN % AES_BLOCK_SIZE == 0, +static_assert(CTR_DRBG_SEED_LEN % AES_BLOCK_SIZE == 0, "not a multiple of AES block size"); // ctr_inc adds |n| to the last four bytes of |drbg->counter|, treated as a @@ -92,22 +244,15 @@ static void ctr32_add(CTR_DRBG_STATE *drbg, uint32_t n) { CRYPTO_store_u32_be(drbg->counter + 12, ctr + n); } -static int ctr_drbg_update(CTR_DRBG_STATE *drbg, const uint8_t *data, - size_t data_len) { - // Per section 10.2.1.2, |data_len| must be |CTR_DRBG_ENTROPY_LEN|. Here, we - // allow shorter inputs and right-pad them with zeros. This is equivalent to - // the specified algorithm but saves a copy in |CTR_DRBG_generate|. - if (data_len > CTR_DRBG_ENTROPY_LEN) { - return 0; - } - - uint8_t temp[CTR_DRBG_ENTROPY_LEN]; - for (size_t i = 0; i < CTR_DRBG_ENTROPY_LEN; i += AES_BLOCK_SIZE) { +static int ctr_drbg_update(CTR_DRBG_STATE *drbg, + const uint8_t data[CTR_DRBG_SEED_LEN]) { + uint8_t temp[CTR_DRBG_SEED_LEN]; + for (size_t i = 0; i < CTR_DRBG_SEED_LEN; i += AES_BLOCK_SIZE) { ctr32_add(drbg, 1); drbg->block(drbg->counter, temp + i, &drbg->ks); } - for (size_t i = 0; i < data_len; i++) { + for (size_t i = 0; i < CTR_DRBG_SEED_LEN; i++) { temp[i] ^= data[i]; } @@ -121,23 +266,46 @@ int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg, const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], const uint8_t *additional_data, size_t additional_data_len) { - // Section 10.2.1.4 - uint8_t entropy_copy[CTR_DRBG_ENTROPY_LEN]; + return CTR_DRBG_reseed_ex(drbg, entropy, CTR_DRBG_ENTROPY_LEN, + additional_data, additional_data_len); +} + +int CTR_DRBG_reseed_ex(CTR_DRBG_STATE *drbg, const uint8_t *entropy, + size_t entropy_len, const uint8_t *additional_data, + size_t additional_data_len) { + if (additional_data_len > CTR_DRBG_SEED_LEN || + (drbg->df && (entropy_len > CTR_DRBG_MAX_ENTROPY_LEN || + entropy_len < CTR_DRBG_MIN_ENTROPY_LEN)) || + (!drbg->df && entropy_len != CTR_DRBG_ENTROPY_LEN)) { + return 0; + } - if (additional_data_len > 0) { - if (additional_data_len > CTR_DRBG_ENTROPY_LEN) { + uint8_t seed_material[CTR_DRBG_SEED_LEN]; + if (drbg->df) { + // Section 10.2.1.4.2 + uint8_t pre_seed_material[CTR_DRBG_MAX_ENTROPY_LEN + CTR_DRBG_SEED_LEN]; + static_assert(CTR_DRBG_MAX_ENTROPY_LEN <= sizeof(pre_seed_material)); + OPENSSL_memcpy(pre_seed_material, entropy, entropy_len); + OPENSSL_memcpy(pre_seed_material + entropy_len, additional_data, + additional_data_len); + const size_t pre_seed_material_len = entropy_len + additional_data_len; + + if (!block_cipher_df(seed_material, sizeof(seed_material), + pre_seed_material, pre_seed_material_len)) { return 0; } - - OPENSSL_memcpy(entropy_copy, entropy, CTR_DRBG_ENTROPY_LEN); - for (size_t i = 0; i < additional_data_len; i++) { - entropy_copy[i] ^= additional_data[i]; + } else { + // Section 10.2.1.4 + static_assert(CTR_DRBG_ENTROPY_LEN == sizeof(seed_material)); + OPENSSL_memcpy(seed_material, entropy, CTR_DRBG_ENTROPY_LEN); + if (additional_data_len > 0) { + for (size_t i = 0; i < additional_data_len; i++) { + seed_material[i] ^= additional_data[i]; + } } - - entropy = entropy_copy; } - if (!ctr_drbg_update(drbg, entropy, CTR_DRBG_ENTROPY_LEN)) { + if (!ctr_drbg_update(drbg, seed_material)) { return 0; } @@ -159,9 +327,26 @@ int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, size_t out_len, return 0; } - if (additional_data_len != 0 && - !ctr_drbg_update(drbg, additional_data, additional_data_len)) { - return 0; + uint8_t processed_additional_data[CTR_DRBG_SEED_LEN]; + OPENSSL_memset(processed_additional_data, 0, + sizeof(processed_additional_data)); + if (additional_data_len != 0) { + if (drbg->df) { + if (!block_cipher_df(processed_additional_data, + sizeof(processed_additional_data), additional_data, + additional_data_len)) { + return 0; + } + } else { + if (additional_data_len > sizeof(processed_additional_data)) { + return 0; + } + OPENSSL_memcpy(processed_additional_data, additional_data, + additional_data_len); + } + if (!ctr_drbg_update(drbg, processed_additional_data)) { + return 0; + } } // kChunkSize is used to interact better with the cache. Since the AES-CTR @@ -170,7 +355,7 @@ int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, size_t out_len, // the whole buffer, flushing the L1 cache, and then do another pass (missing // the cache every time) to “encrypt” it. The code can avoid this by // chunking. - static const size_t kChunkSize = 8 * 1024; + constexpr size_t kChunkSize = 8 * 1024; while (out_len >= AES_BLOCK_SIZE) { size_t todo = kChunkSize; @@ -198,9 +383,7 @@ int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, size_t out_len, OPENSSL_memcpy(out, block, out_len); } - // Right-padding |additional_data| in step 2.2 is handled implicitly by - // |ctr_drbg_update|, to save a copy. - if (!ctr_drbg_update(drbg, additional_data, additional_data_len)) { + if (!ctr_drbg_update(drbg, processed_additional_data)) { return 0; } diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/internal.h b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/internal.h index 2d2262939..3913ff8df 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/internal.h @@ -37,14 +37,19 @@ struct ctr_drbg_state_st { ctr128_f ctr; uint8_t counter[16]; uint64_t reseed_counter; + int df; }; -// CTR_DRBG_init initialises |*drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of -// entropy in |entropy| and, optionally, a personalization string up to -// |CTR_DRBG_ENTROPY_LEN| bytes in length. It returns one on success and zero -// on error. -OPENSSL_EXPORT int CTR_DRBG_init(CTR_DRBG_STATE *drbg, - const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], +// CTR_DRBG_init initialises |*drbg| given |entropy_len| bytes of entropy in +// |entropy| and, optionally, a personalization string up to +// |CTR_DRBG_SEED_LEN| bytes in length. It returns one on success and zero on +// error. +// +// If `df` is false then `entropy_len` must be |CTR_DRBG_ENTROPY_LEN| and +// |nonce| must be nullptr. +OPENSSL_EXPORT int CTR_DRBG_init(CTR_DRBG_STATE *drbg, int df, + const uint8_t *entropy, size_t entropy_len, + const uint8_t nonce[CTR_DRBG_NONCE_LEN], const uint8_t *personalization, size_t personalization_len); diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/rand.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/rand.cc.inc index 96e7381e6..82cc41c42 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/rand.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rand/rand.cc.inc @@ -187,8 +187,7 @@ bcm_status BCM_rand_bytes_hwrng(uint8_t *buf, const size_t len) { struct entropy_buffer { // bytes contains entropy suitable for seeding a DRBG. - uint8_t - bytes[CRNGT_BLOCK_SIZE + CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD]; + uint8_t bytes[CRNGT_BLOCK_SIZE + CTR_DRBG_SEED_LEN * BORINGSSL_FIPS_OVERREAD]; // bytes_valid indicates the number of bytes of |bytes| that contain valid // data. size_t bytes_valid; @@ -250,11 +249,11 @@ static void get_seed_entropy(uint8_t *out_entropy, size_t out_entropy_len, // fill |additional_input| with entropy to supplement |seed|. It sets // |*out_additional_input_len| to the number of extra bytes. static void rand_get_seed(struct rand_thread_state *state, - uint8_t seed[CTR_DRBG_ENTROPY_LEN], - uint8_t additional_input[CTR_DRBG_ENTROPY_LEN], + uint8_t seed[CTR_DRBG_SEED_LEN], + uint8_t additional_input[CTR_DRBG_SEED_LEN], size_t *out_additional_input_len) { uint8_t entropy_bytes[sizeof(state->last_block) + - CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD]; + CTR_DRBG_SEED_LEN * BORINGSSL_FIPS_OVERREAD]; uint8_t *entropy = entropy_bytes; size_t entropy_len = sizeof(entropy_bytes); @@ -293,12 +292,12 @@ static void rand_get_seed(struct rand_thread_state *state, OPENSSL_memcpy(state->last_block, entropy + entropy_len - CRNGT_BLOCK_SIZE, CRNGT_BLOCK_SIZE); - assert(entropy_len == BORINGSSL_FIPS_OVERREAD * CTR_DRBG_ENTROPY_LEN); - OPENSSL_memcpy(seed, entropy, CTR_DRBG_ENTROPY_LEN); + assert(entropy_len == BORINGSSL_FIPS_OVERREAD * CTR_DRBG_SEED_LEN); + OPENSSL_memcpy(seed, entropy, CTR_DRBG_SEED_LEN); for (size_t i = 1; i < BORINGSSL_FIPS_OVERREAD; i++) { - for (size_t j = 0; j < CTR_DRBG_ENTROPY_LEN; j++) { - seed[j] ^= entropy[CTR_DRBG_ENTROPY_LEN * i + j]; + for (size_t j = 0; j < CTR_DRBG_SEED_LEN; j++) { + seed[j] ^= entropy[CTR_DRBG_SEED_LEN * i + j]; } } @@ -307,8 +306,8 @@ static void rand_get_seed(struct rand_thread_state *state, // hardware once the entropy pool has been initialized. *out_additional_input_len = 0; if (want_additional_input && - CRYPTO_sysrand_if_available(additional_input, CTR_DRBG_ENTROPY_LEN)) { - *out_additional_input_len = CTR_DRBG_ENTROPY_LEN; + CRYPTO_sysrand_if_available(additional_input, CTR_DRBG_SEED_LEN)) { + *out_additional_input_len = CTR_DRBG_SEED_LEN; } } @@ -318,12 +317,12 @@ static void rand_get_seed(struct rand_thread_state *state, // fill |additional_input| with entropy to supplement |seed|. It sets // |*out_additional_input_len| to the number of extra bytes. static void rand_get_seed(struct rand_thread_state *state, - uint8_t seed[CTR_DRBG_ENTROPY_LEN], - uint8_t additional_input[CTR_DRBG_ENTROPY_LEN], + uint8_t seed[CTR_DRBG_SEED_LEN], + uint8_t additional_input[CTR_DRBG_SEED_LEN], size_t *out_additional_input_len) { // If not in FIPS mode, we don't overread from the system entropy source and // we don't depend only on the hardware RDRAND. - CRYPTO_sysrand_for_seed(seed, CTR_DRBG_ENTROPY_LEN); + CRYPTO_sysrand_for_seed(seed, CTR_DRBG_SEED_LEN); *out_additional_input_len = 0; } @@ -384,13 +383,13 @@ bcm_infallible BCM_rand_bytes_with_additional_data( } state->last_block_valid = 0; - uint8_t seed[CTR_DRBG_ENTROPY_LEN]; - uint8_t personalization[CTR_DRBG_ENTROPY_LEN] = {0}; + uint8_t seed[CTR_DRBG_SEED_LEN]; + uint8_t personalization[CTR_DRBG_SEED_LEN] = {0}; size_t personalization_len = 0; rand_get_seed(state, seed, personalization, &personalization_len); - if (!CTR_DRBG_init(&state->drbg, seed, personalization, - personalization_len)) { + if (!CTR_DRBG_init(&state->drbg, /*df=*/true, seed, 32u, seed + 32, + personalization, personalization_len)) { abort(); } state->calls = 0; @@ -422,8 +421,8 @@ bcm_infallible BCM_rand_bytes_with_additional_data( // safety. The children must reseed to avoid working from the same PRNG // state. state->fork_unsafe_buffering != fork_unsafe_buffering) { - uint8_t seed[CTR_DRBG_ENTROPY_LEN]; - uint8_t reseed_additional_data[CTR_DRBG_ENTROPY_LEN] = {0}; + uint8_t seed[CTR_DRBG_SEED_LEN]; + uint8_t reseed_additional_data[CTR_DRBG_SEED_LEN] = {0}; size_t reseed_additional_data_len = 0; rand_get_seed(state, seed, reseed_additional_data, &reseed_additional_data_len); @@ -433,8 +432,9 @@ bcm_infallible BCM_rand_bytes_with_additional_data( // |rand_thread_state_clear_all|. CRYPTO_MUTEX_lock_read(&state->clear_drbg_lock); #endif - if (!CTR_DRBG_reseed(&state->drbg, seed, reseed_additional_data, - reseed_additional_data_len)) { + if (!CTR_DRBG_reseed_ex(&state->drbg, seed, sizeof(seed), + reseed_additional_data, + reseed_additional_data_len)) { abort(); } state->calls = 0; diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/padding.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/padding.cc.inc index 2bd0ba9c7..c796122e6 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/padding.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/padding.cc.inc @@ -178,16 +178,14 @@ int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, size_t emLen, maskedDBLen, salt_start; FIPS_service_indicator_lock_state(); - // Negative sLen has special meanings: - // -1 sLen == hLen - // -2 salt length is autorecovered from signature - // -N reserved size_t hLen = EVP_MD_size(Hash); - if (sLen == -1) { + if (sLen == RSA_PSS_SALTLEN_DIGEST) { sLen = (int)hLen; - } else if (sLen == -2) { - sLen = -2; - } else if (sLen < -2) { + } else if (sLen == RSA_PSS_SALTLEN_AUTO) { + // Leave |sLen| negative, which will trigger the logic below to recover and + // allow any salt length. + } else if (sLen < 0) { + // Other negative values are reserved. OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); goto err; } @@ -202,7 +200,7 @@ int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, EM++; emLen--; } - // |sLen| may be -2 for the non-standard salt length recovery mode. + // |sLen| may be negative for the non-standard salt length recovery mode. if (emLen < hLen + 2 || (sLen >= 0 && emLen < hLen + (size_t)sLen + 2)) { OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); goto err; @@ -299,16 +297,14 @@ int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, unsigned char *EM, goto err; } - // Negative sLenRequested has special meanings: - // -1 sLen == hLen - // -2 salt length is maximized - // -N reserved size_t sLen; - if (sLenRequested == -1) { + if (sLenRequested == RSA_PSS_SALTLEN_DIGEST) { sLen = hLen; - } else if (sLenRequested == -2) { + } else if (sLenRequested == RSA_PSS_SALTLEN_AUTO) { + // Use the maximum possible salt length. sLen = emLen - hLen - 2; } else if (sLenRequested < 0) { + // Other negative values are reserved. OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); goto err; } else { diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa.cc.inc index 3187658f1..0884e7d00 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa.cc.inc @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -276,12 +278,6 @@ void RSA_get0_factors(const RSA *rsa, const BIGNUM **out_p, } } -const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *rsa) { - // We do not support the id-RSASSA-PSS key encoding. If we add support later, - // the |maskHash| field should be filled in for OpenSSL compatibility. - return NULL; -} - void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1, const BIGNUM **out_dmq1, const BIGNUM **out_iqmp) { if (out_dmp1 != NULL) { @@ -875,8 +871,8 @@ static const BN_ULONG kSmallFactorsLimbs[] = {TOBN(0xc4309333, 0x3ef4e3e1), 0x000017b1}; DEFINE_LOCAL_DATA(BIGNUM, g_small_factors) { - out->d = (BN_ULONG *)kSmallFactorsLimbs; - out->width = OPENSSL_ARRAY_SIZE(kSmallFactorsLimbs); + out->d = const_cast(kSmallFactorsLimbs); + out->width = std::size(kSmallFactorsLimbs); out->dmax = out->width; out->neg = 0; out->flags = BN_FLG_STATIC_DATA; diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa_impl.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa_impl.cc.inc index 29c388970..8689e09b2 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa_impl.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/rsa/rsa_impl.cc.inc @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -840,7 +842,7 @@ const BN_ULONG kBoringSSLRSASqrtTwo[] = { TOBN(0xed17ac85, 0x83339915), TOBN(0x1d6f60ba, 0x893ba84c), TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484), }; -const size_t kBoringSSLRSASqrtTwoLen = OPENSSL_ARRAY_SIZE(kBoringSSLRSASqrtTwo); +const size_t kBoringSSLRSASqrtTwoLen = std::size(kBoringSSLRSASqrtTwo); // generate_prime sets |out| to a prime with length |bits| such that |out|-1 is // relatively prime to |e|. If |p| is non-NULL, |out| will also not be close to @@ -1183,9 +1185,7 @@ static int RSA_generate_key_ex_maybe_fips(RSA *rsa, int bits, return 0; } - RSA *tmp = NULL; - uint32_t err; - int ret = 0; + bssl::UniquePtr tmp; // |rsa_generate_key_impl|'s 2^-20 failure probability is too high at scale, // so we run the FIPS algorithm four times, bringing it down to 2^-80. We @@ -1195,27 +1195,25 @@ static int RSA_generate_key_ex_maybe_fips(RSA *rsa, int bits, do { ERR_clear_error(); // Generate into scratch space, to avoid leaving partial work on failure. - tmp = RSA_new(); - if (tmp == NULL) { - goto out; + tmp.reset(RSA_new()); + if (tmp == nullptr) { + return 0; } - if (rsa_generate_key_impl(tmp, bits, e_value, cb)) { + if (rsa_generate_key_impl(tmp.get(), bits, e_value, cb)) { break; } - err = ERR_peek_error(); - RSA_free(tmp); - tmp = NULL; + tmp = nullptr; failures++; // Only retry on |RSA_R_TOO_MANY_ITERATIONS|. This is so a caller-induced // failure in |BN_GENCB_call| is still fatal. - } while (failures < 4 && ERR_GET_LIB(err) == ERR_LIB_RSA && - ERR_GET_REASON(err) == RSA_R_TOO_MANY_ITERATIONS); + } while (failures < 4 && ERR_equals(ERR_peek_error(), ERR_LIB_RSA, + RSA_R_TOO_MANY_ITERATIONS)); - if (tmp == NULL || (check_fips && !RSA_check_fips(tmp))) { - goto out; + if (tmp == nullptr || (check_fips && !RSA_check_fips(tmp.get()))) { + return 0; } rsa_invalidate_key(rsa); @@ -1235,11 +1233,7 @@ static int RSA_generate_key_ex_maybe_fips(RSA *rsa, int bits, replace_bignum(&rsa->dmq1_fixed, &tmp->dmq1_fixed); replace_bignum(&rsa->iqmp_mont, &tmp->iqmp_mont); rsa->private_key_frozen = tmp->private_key_frozen; - ret = 1; - -out: - RSA_free(tmp); - return ret; + return 1; } int RSA_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e_value, diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/fips.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/fips.cc.inc index 187c38556..56f7e4b0b 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/fips.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/fips.cc.inc @@ -67,8 +67,8 @@ int FIPS_query_algorithm_status(const char *algorithm) { "SHA2-512", "SHA2-512/256", }; - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kApprovedAlgorithms); i++) { - if (strcmp(algorithm, kApprovedAlgorithms[i]) == 0) { + for (const char *approved : kApprovedAlgorithms) { + if (strcmp(algorithm, approved) == 0) { return 1; } } diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/self_check.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/self_check.cc.inc index 2184d3ec2..6ab9abe98 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/self_check.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/self_check/self_check.cc.inc @@ -17,6 +17,8 @@ #include #include +#include + #include #include #include @@ -269,7 +271,7 @@ static DH *self_test_dh(void) { }; bn_set_static_words(priv, kFFDHE2048PrivateKeyData, - OPENSSL_ARRAY_SIZE(kFFDHE2048PrivateKeyData)); + std::size(kFFDHE2048PrivateKeyData)); if (!DH_set0_key(dh, NULL, priv)) { goto err; @@ -569,7 +571,7 @@ static int boringssl_self_test_ffdh(void) { ffdhe2048_value = BN_new(); if (ffdhe2048_value) { bn_set_static_words(ffdhe2048_value, kFFDHE2048PublicValueData, - OPENSSL_ARRAY_SIZE(kFFDHE2048PublicValueData)); + std::size(kFFDHE2048PublicValueData)); } dh = self_test_dh(); @@ -840,11 +842,14 @@ static int boringssl_self_test_fast(void) { } // DBRG KAT - static const uint8_t kDRBGEntropy[48] = { - 0xc4, 0xda, 0x07, 0x40, 0xd5, 0x05, 0xf1, 0xee, 0x28, 0x0b, 0x95, 0xe5, - 0x8c, 0x49, 0x31, 0xac, 0x6d, 0xe8, 0x46, 0xa0, 0x15, 0x2f, 0xbb, 0x4a, - 0x3f, 0x17, 0x4c, 0xf4, 0x78, 0x7a, 0x4f, 0x1a, 0x40, 0xc2, 0xb5, 0x0b, - 0xab, 0xe1, 0x4a, 0xae, 0x53, 0x0b, 0xe5, 0x88, 0x6d, 0x91, 0x0a, 0x27, + static const uint8_t kDRBGEntropy[32] = { + 0xc4, 0xda, 0x07, 0x40, 0xd5, 0x05, 0xf1, 0xee, 0x28, 0x0b, 0x95, + 0xe5, 0x8c, 0x49, 0x31, 0xac, 0x6d, 0xe8, 0x46, 0xa0, 0x15, 0x2f, + 0xbb, 0x4a, 0x3f, 0x17, 0x4c, 0xf4, 0x78, 0x7a, 0x4f, 0x1a, + }; + static const uint8_t kDRBGNonce[CTR_DRBG_NONCE_LEN] = { + 0x40, 0xc2, 0xb5, 0x0b, 0xab, 0xe1, 0x4a, 0xae, + 0x53, 0x0b, 0xe5, 0x88, 0x6d, 0x91, 0x0a, 0x27, }; static const uint8_t kDRBGPersonalization[18] = { 'B', 'C', 'M', 'P', 'e', 'r', 's', 'o', 'n', @@ -852,12 +857,12 @@ static int boringssl_self_test_fast(void) { static const uint8_t kDRBGAD[16] = {'B', 'C', 'M', ' ', 'D', 'R', 'B', 'G', ' ', 'K', 'A', 'T', ' ', 'A', 'D', ' '}; static const uint8_t kDRBGOutput[64] = { - 0x19, 0x1f, 0x2b, 0x49, 0x76, 0x85, 0xfd, 0x51, 0xb6, 0x56, 0xbc, - 0x1c, 0x7d, 0xd5, 0xdd, 0x44, 0x76, 0xa3, 0x5e, 0x17, 0x9b, 0x8e, - 0xb8, 0x98, 0x65, 0x12, 0xca, 0x35, 0x6c, 0xa0, 0x6f, 0xa0, 0x22, - 0xe4, 0xf6, 0xd8, 0x43, 0xed, 0x4e, 0x2d, 0x97, 0x39, 0x43, 0x3b, - 0x57, 0xfc, 0x23, 0x3f, 0x71, 0x0a, 0xe0, 0xed, 0xfe, 0xd5, 0xb8, - 0x67, 0x7a, 0x00, 0x39, 0xb2, 0x6e, 0xa9, 0x25, 0x97, + 0x55, 0x88, 0x81, 0x88, 0x16, 0x49, 0x68, 0xd8, 0x23, 0xc8, 0x18, + 0x57, 0x5d, 0x06, 0xc3, 0x5f, 0x60, 0x3a, 0xe8, 0xfe, 0x7c, 0x7e, + 0x1c, 0x4a, 0x6a, 0xa8, 0x91, 0x07, 0xc0, 0x0d, 0x1f, 0x70, 0x4a, + 0xbb, 0x20, 0x42, 0xd3, 0x3f, 0x19, 0xf1, 0xb1, 0xfc, 0xef, 0xa1, + 0x71, 0xfd, 0xf7, 0xaf, 0xc5, 0x12, 0x7a, 0x98, 0xad, 0x42, 0xbc, + 0x01, 0xe6, 0xa2, 0x83, 0xbc, 0x73, 0xb5, 0xba, 0x84, }; static const uint8_t kDRBGEntropy2[48] = { 0xc7, 0x16, 0x1c, 0xa3, 0x6c, 0x23, 0x09, 0xb7, 0x16, 0xe9, 0x85, 0x9b, @@ -866,21 +871,23 @@ static int boringssl_self_test_fast(void) { 0x76, 0xc1, 0x86, 0xe9, 0x35, 0x18, 0x03, 0x76, 0x3a, 0x79, 0x12, 0xfe, }; static const uint8_t kDRBGReseedOutput[64] = { - 0x00, 0xf2, 0x05, 0xaa, 0xfd, 0x11, 0x6c, 0x77, 0xbc, 0x81, 0x86, - 0x99, 0xca, 0x51, 0xcf, 0x80, 0x15, 0x9f, 0x02, 0x9e, 0x0b, 0xcd, - 0x26, 0xc8, 0x4b, 0x87, 0x8a, 0x15, 0x1a, 0xdd, 0xf2, 0xf3, 0xeb, - 0x94, 0x0b, 0x08, 0xc8, 0xc9, 0x57, 0xa4, 0x0b, 0x4b, 0x0f, 0x13, - 0xde, 0x7c, 0x0c, 0x6a, 0xac, 0x34, 0x4a, 0x9a, 0xf2, 0xd0, 0x83, - 0x02, 0x05, 0x17, 0xc9, 0x81, 0x8f, 0x2a, 0x81, 0x92, + 0xda, 0x49, 0xa1, 0x01, 0x31, 0x71, 0x77, 0xde, 0xf6, 0x8d, 0xb5, + 0x4f, 0x86, 0x0d, 0xc8, 0xd6, 0x3c, 0xaa, 0xbc, 0x72, 0x0a, 0x9c, + 0x8b, 0x68, 0xa9, 0x70, 0xf1, 0x21, 0x13, 0xce, 0xc6, 0xbc, 0xff, + 0xaf, 0xa8, 0xd5, 0x26, 0x76, 0x26, 0xcc, 0x0d, 0x89, 0x66, 0xab, + 0xc2, 0x11, 0xa8, 0x2f, 0xf1, 0x36, 0xa3, 0x2b, 0x52, 0xcd, 0x1a, + 0x2d, 0xe4, 0x82, 0xac, 0x3c, 0xbb, 0xa9, 0x17, 0x90, }; CTR_DRBG_STATE drbg; - if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization, + if (!CTR_DRBG_init(&drbg, /*df=*/true, kDRBGEntropy, sizeof(kDRBGEntropy), + kDRBGNonce, kDRBGPersonalization, sizeof(kDRBGPersonalization)) || !CTR_DRBG_generate(&drbg, output, sizeof(kDRBGOutput), kDRBGAD, sizeof(kDRBGAD)) || !BORINGSSL_check_test(kDRBGOutput, output, sizeof(kDRBGOutput), "DRBG Generate KAT") || - !CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) || + !CTR_DRBG_reseed_ex(&drbg, kDRBGEntropy2, sizeof(kDRBGEntropy2), kDRBGAD, + sizeof(kDRBGAD)) || !CTR_DRBG_generate(&drbg, output, sizeof(kDRBGReseedOutput), kDRBGAD, sizeof(kDRBGAD)) || !BORINGSSL_check_test(kDRBGReseedOutput, output, diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h b/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h index c5a8113c8..27f806036 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h @@ -17,6 +17,9 @@ #include +#if defined(__cplusplus) +extern "C" { +#endif // FIPS_service_indicator_before_call and |FIPS_service_indicator_after_call| // both currently return the same local thread counter which is slowly @@ -37,6 +40,10 @@ OPENSSL_EXPORT uint64_t FIPS_service_indicator_before_call(void); OPENSSL_EXPORT uint64_t FIPS_service_indicator_after_call(void); +#if defined(__cplusplus) +} +#endif + #if defined(BORINGSSL_FIPS) // FIPS_service_indicator_update_state records that an approved service has been diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc index 6f2e6c285..aed88be7a 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc @@ -217,7 +217,8 @@ static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx, const EVP_MD *mgf1_md; if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pctx, &salt_len) || !EVP_PKEY_CTX_get_rsa_mgf1_md(pctx, &mgf1_md) || - (salt_len != -1 && salt_len != (int)EVP_MD_size(pctx_md)) || + (salt_len != RSA_PSS_SALTLEN_DIGEST && + salt_len != (int)EVP_MD_size(pctx_md)) || EVP_MD_type(mgf1_md) != md_type) { // Only PSS where saltLen == hashLen is tested with ACVP. Cases with // non-standard padding functions are also excluded. diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc index b11f39824..8cbf88590 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc @@ -40,8 +40,8 @@ bcm_infallible BCM_sha384_init(SHA512_CTX *sha) { sha->h[6] = UINT64_C(0xdb0c2e0d64f98fa7); sha->h[7] = UINT64_C(0x47b5481dbefa4fa4); - sha->Nl = 0; - sha->Nh = 0; + sha->bytes_so_far_low = 0; + sha->bytes_so_far_high = 0; sha->num = 0; sha->md_len = BCM_SHA384_DIGEST_LENGTH; return bcm_infallible::approved; @@ -58,8 +58,8 @@ bcm_infallible BCM_sha512_init(SHA512_CTX *sha) { sha->h[6] = UINT64_C(0x1f83d9abfb41bd6b); sha->h[7] = UINT64_C(0x5be0cd19137e2179); - sha->Nl = 0; - sha->Nh = 0; + sha->bytes_so_far_low = 0; + sha->bytes_so_far_high = 0; sha->num = 0; sha->md_len = BCM_SHA512_DIGEST_LENGTH; return bcm_infallible::approved; @@ -75,8 +75,8 @@ bcm_infallible BCM_sha512_256_init(SHA512_CTX *sha) { sha->h[6] = UINT64_C(0x2b0199fc2c85b8aa); sha->h[7] = UINT64_C(0x0eb72ddc81c52ca2); - sha->Nl = 0; - sha->Nh = 0; + sha->bytes_so_far_low = 0; + sha->bytes_so_far_high = 0; sha->num = 0; sha->md_len = BCM_SHA512_256_DIGEST_LENGTH; return bcm_infallible::approved; @@ -124,7 +124,6 @@ bcm_infallible BCM_sha512_transform(SHA512_CTX *c, bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, size_t len) { - uint64_t l; uint8_t *p = c->p; const uint8_t *data = reinterpret_cast(in_data); @@ -132,14 +131,10 @@ bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, return bcm_infallible::approved; } - l = (c->Nl + (((uint64_t)len) << 3)) & UINT64_C(0xffffffffffffffff); - if (l < c->Nl) { - c->Nh++; + c->bytes_so_far_low += len; + if (c->bytes_so_far_low < len) { + c->bytes_so_far_high++; } - if (sizeof(len) >= 8) { - c->Nh += (((uint64_t)len) >> 61); - } - c->Nl = l; if (c->num != 0) { size_t n = sizeof(c->p) - c->num; @@ -195,8 +190,11 @@ static void sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha) { } OPENSSL_memset(p + n, 0, sizeof(sha->p) - 16 - n); - CRYPTO_store_u64_be(p + sizeof(sha->p) - 16, sha->Nh); - CRYPTO_store_u64_be(p + sizeof(sha->p) - 8, sha->Nl); + const uint64_t Nh = (uint64_t{sha->bytes_so_far_high} << 3) | + (sha->bytes_so_far_low >> (64 - 3)); + const uint64_t Nl = sha->bytes_so_far_low << 3; + CRYPTO_store_u64_be(p + sizeof(sha->p) - 16, Nh); + CRYPTO_store_u64_be(p + sizeof(sha->p) - 8, Nl); sha512_block_data_order(sha->h, p, 1); diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/slhdsa/thash.cc.inc b/Sources/CCryptoBoringSSL/crypto/fipsmodule/slhdsa/thash.cc.inc index ec3084d12..3183061bd 100644 --- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/slhdsa/thash.cc.inc +++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/slhdsa/thash.cc.inc @@ -17,7 +17,7 @@ #include #include -#include +#include #include "../../internal.h" #include "./params.h" diff --git a/Sources/CCryptoBoringSSL/crypto/hpke/hpke.cc b/Sources/CCryptoBoringSSL/crypto/hpke/hpke.cc index 63a360d02..684c27963 100644 --- a/Sources/CCryptoBoringSSL/crypto/hpke/hpke.cc +++ b/Sources/CCryptoBoringSSL/crypto/hpke/hpke.cc @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include #include "../fipsmodule/ec/internal.h" #include "../internal.h" @@ -35,7 +36,7 @@ // This file implements RFC 9180. -#define MAX_SEED_LEN X25519_PRIVATE_KEY_LEN +#define MAX_SEED_LEN XWING_SEED_LEN #define MAX_SHARED_SECRET_LEN SHA256_DIGEST_LENGTH struct evp_hpke_kem_st { @@ -601,6 +602,122 @@ const EVP_HPKE_KEM *EVP_hpke_p256_hkdf_sha256(void) { return &kKEM; } +#define XWING_PRIVATE_KEY_LEN 32 +#define XWING_PUBLIC_KEY_LEN 1216 +#define XWING_PUBLIC_VALUE_LEN 1120 +#define XWING_SEED_LEN 64 +#define XWING_SHARED_KEY_LEN 32 + +static int xwing_init_key(EVP_HPKE_KEY *key, const uint8_t *priv_key, + size_t priv_key_len) { + CBS cbs; + CBS_init(&cbs, priv_key, priv_key_len); + XWING_private_key private_key; + if (!XWING_parse_private_key(&private_key, &cbs) || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + if (!XWING_public_from_private(key->public_key, &private_key)) { + return 0; + } + + if (priv_key_len > sizeof(key->private_key)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + OPENSSL_memcpy(key->private_key, priv_key, priv_key_len); + return 1; +} + +static int xwing_generate_key(EVP_HPKE_KEY *key) { + XWING_private_key private_key; + if (!XWING_generate_key(key->public_key, &private_key)) { + return 0; + } + + CBB cbb; + CBB_init_fixed(&cbb, key->private_key, XWING_PRIVATE_KEY_LEN); + if (!XWING_marshal_private_key(&cbb, &private_key) || + CBB_len(&cbb) != XWING_PRIVATE_KEY_LEN) { + return 0; + } + + return 1; +} + +static int xwing_encap_with_seed(const EVP_HPKE_KEM *kem, + uint8_t *out_shared_secret, + size_t *out_shared_secret_len, + uint8_t *out_enc, size_t *out_enc_len, + size_t max_enc, const uint8_t *peer_public_key, + size_t peer_public_key_len, + const uint8_t *seed, size_t seed_len) { + if (max_enc < XWING_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE); + return 0; + } + if (peer_public_key_len != XWING_PUBLIC_KEY_LEN || + seed_len != XWING_SEED_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + if (!XWING_encap_external_entropy(out_enc, out_shared_secret, peer_public_key, + seed)) { + OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + + *out_enc_len = XWING_PUBLIC_VALUE_LEN; + *out_shared_secret_len = XWING_SHARED_KEY_LEN; + return 1; +} + +static int xwing_decap(const EVP_HPKE_KEY *key, uint8_t *out_shared_secret, + size_t *out_shared_secret_len, const uint8_t *enc, + size_t enc_len) { + if (enc_len != XWING_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + CBS cbs; + CBS_init(&cbs, key->private_key, XWING_PRIVATE_KEY_LEN); + XWING_private_key private_key; + if (!XWING_parse_private_key(&private_key, &cbs)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + + if (!XWING_decap(out_shared_secret, enc, &private_key)) { + OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + + *out_shared_secret_len = XWING_SHARED_KEY_LEN; + return 1; +} + +const EVP_HPKE_KEM *EVP_hpke_xwing(void) { + static const EVP_HPKE_KEM kKEM = { + /*id=*/EVP_HPKE_XWING, + /*public_key_len=*/XWING_PUBLIC_KEY_LEN, + /*private_key_len=*/XWING_PRIVATE_KEY_LEN, + /*seed_len=*/XWING_SEED_LEN, + /*enc_len=*/XWING_PUBLIC_VALUE_LEN, + xwing_init_key, + xwing_generate_key, + xwing_encap_with_seed, + xwing_decap, + // X-Wing doesn't support authenticated encapsulation/decapsulation: + // https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-08#name-use-in-hpke + /* auth_encap_with_seed= */ nullptr, + /* auth_decap= */ nullptr, + }; + return &kKEM; +} + uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem) { return kem->id; } size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem) { diff --git a/Sources/CCryptoBoringSSL/crypto/hrss/hrss.cc b/Sources/CCryptoBoringSSL/crypto/hrss/hrss.cc index 457bdb663..3b2031e5a 100644 --- a/Sources/CCryptoBoringSSL/crypto/hrss/hrss.cc +++ b/Sources/CCryptoBoringSSL/crypto/hrss/hrss.cc @@ -17,13 +17,15 @@ #include #include #include + +#include #include #include #include #include #include -#include +#include #include "../internal.h" #include "internal.h" @@ -309,7 +311,7 @@ static crypto_word_t word_reverse(crypto_word_t in) { }; #endif - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMasks); i++) { + for (size_t i = 0; i < std::size(kMasks); i++) { in = ((in >> (1 << i)) & kMasks[i]) | ((in & kMasks[i]) << (1 << i)); } diff --git a/Sources/CCryptoBoringSSL/crypto/internal.h b/Sources/CCryptoBoringSSL/crypto/internal.h index 90d70645f..f371bcb5c 100644 --- a/Sources/CCryptoBoringSSL/crypto/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/internal.h @@ -23,6 +23,8 @@ #include #include +#include + #if defined(BORINGSSL_CONSTANT_TIME_VALIDATION) #include #endif @@ -50,6 +52,10 @@ #include #endif +#if defined(_M_X64) || defined(_M_IX86) +#include "intrin.h" +#endif + #if defined(__cplusplus) extern "C" { #endif @@ -100,8 +106,6 @@ typedef __uint128_t uint128_t; #endif #endif -#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) - // GCC-like compilers indicate SSE2 with |__SSE2__|. MSVC leaves the caller to // know that x86_64 has SSE2, and uses _M_IX86_FP to indicate SSE2 on x86. // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170 @@ -527,8 +531,6 @@ OPENSSL_EXPORT void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)); using CRYPTO_atomic_u32 = std::atomic; -static_assert(sizeof(CRYPTO_atomic_u32) == sizeof(uint32_t)); - inline uint32_t CRYPTO_atomic_load_u32(const CRYPTO_atomic_u32 *val) { return val->load(std::memory_order_seq_cst); } @@ -567,12 +569,6 @@ inline void CRYPTO_atomic_store_u32(CRYPTO_atomic_u32 *val, uint32_t desired) { #endif -// See the comment in the |__cplusplus| section above. -static_assert(sizeof(CRYPTO_atomic_u32) == sizeof(uint32_t), - "CRYPTO_atomic_u32 does not match uint32_t size"); -static_assert(alignof(CRYPTO_atomic_u32) == alignof(uint32_t), - "CRYPTO_atomic_u32 does not match uint32_t alignment"); - // Reference counting. @@ -886,6 +882,16 @@ static inline void *OPENSSL_memset(void *dst, int c, size_t n) { // endianness. They use |memcpy|, and so avoid alignment or strict aliasing // requirements on the input and output pointers. +static inline uint16_t CRYPTO_load_u16_le(const void *in) { + uint16_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); + return v; +} + +static inline void CRYPTO_store_u16_le(void *out, uint16_t v) { + OPENSSL_memcpy(out, &v, sizeof(v)); +} + static inline uint16_t CRYPTO_load_u16_be(const void *in) { uint16_t v; OPENSSL_memcpy(&v, in, sizeof(v)); @@ -1444,6 +1450,9 @@ inline int CRYPTO_fuzzer_mode_enabled(void) { return 0; } // CRYPTO_addc_* returns |x + y + carry|, and sets |*out_carry| to the carry // bit. |carry| must be zero or one. + +// NOTE: Unoptimized GCC builds may compile these builtins to non-constant-time +// code. For correct constant-time behavior, ensure builds are optimized. #if OPENSSL_HAS_BUILTIN(__builtin_addc) inline unsigned int CRYPTO_addc_impl(unsigned int x, unsigned int y, @@ -1480,16 +1489,26 @@ inline uint64_t CRYPTO_addc_u64(uint64_t x, uint64_t y, uint64_t carry, static inline uint32_t CRYPTO_addc_u32(uint32_t x, uint32_t y, uint32_t carry, uint32_t *out_carry) { declassify_assert(carry <= 1); +#if defined(_M_IX86) + uint32_t sum = 0; + *out_carry = _addcarry_u32(carry, x, y, &sum); + return sum; +#else uint64_t ret = carry; ret += (uint64_t)x + y; *out_carry = (uint32_t)(ret >> 32); return (uint32_t)ret; +#endif } static inline uint64_t CRYPTO_addc_u64(uint64_t x, uint64_t y, uint64_t carry, uint64_t *out_carry) { declassify_assert(carry <= 1); -#if defined(BORINGSSL_HAS_UINT128) +#if defined(_M_X64) + uint64_t sum = 0; + *out_carry = _addcarry_u64(carry, x, y, &sum); + return sum; +#elif defined(BORINGSSL_HAS_UINT128) uint128_t ret = carry; ret += (uint128_t)x + y; *out_carry = (uint64_t)(ret >> 64); @@ -1544,17 +1563,29 @@ inline uint64_t CRYPTO_subc_u64(uint64_t x, uint64_t y, uint64_t borrow, static inline uint32_t CRYPTO_subc_u32(uint32_t x, uint32_t y, uint32_t borrow, uint32_t *out_borrow) { declassify_assert(borrow <= 1); +#if defined(_M_IX86) + uint32_t diff = 0; + *out_borrow = _subborrow_u32(borrow, x, y, &diff); + return diff; +#else uint32_t ret = x - y - borrow; *out_borrow = (x < y) | ((x == y) & borrow); return ret; +#endif } static inline uint64_t CRYPTO_subc_u64(uint64_t x, uint64_t y, uint64_t borrow, uint64_t *out_borrow) { declassify_assert(borrow <= 1); +#if defined(_M_X64) + uint64_t diff = 0; + *out_borrow = _subborrow_u64(borrow, x, y, &diff); + return diff; +#else uint64_t ret = x - y - borrow; *out_borrow = (x < y) | ((x == y) & borrow); return ret; +#endif } #endif @@ -1567,4 +1598,28 @@ static inline uint64_t CRYPTO_subc_u64(uint64_t x, uint64_t y, uint64_t borrow, #endif +BSSL_NAMESPACE_BEGIN +// Cleanup implements a custom scope guard, when the cleanup logic does not fit +// in a destructor. Usage: +// +// bssl::Cleanup cleanup = [&] { SomeCleanupWork(local_var); }; +template +class Cleanup { + public: + static_assert(std::is_invocable_v); + static_assert(std::is_same_v, void>); + + Cleanup(F func) : func_(func) {} + Cleanup(const Cleanup &) = delete; + Cleanup &operator=(const Cleanup &) = delete; + ~Cleanup() { func_(); } + + private: + F func_; +}; +template +Cleanup(F func) -> Cleanup; +BSSL_NAMESPACE_END + + #endif // OPENSSL_HEADER_CRYPTO_INTERNAL_H diff --git a/Sources/CCryptoBoringSSL/crypto/kyber/internal.h b/Sources/CCryptoBoringSSL/crypto/kyber/internal.h index 0d8dc06dc..c7a8d42d6 100644 --- a/Sources/CCryptoBoringSSL/crypto/kyber/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/kyber/internal.h @@ -16,13 +16,122 @@ #define OPENSSL_HEADER_CRYPTO_KYBER_INTERNAL_H #include -#include #if defined(__cplusplus) extern "C" { #endif +// Kyber is the pre-standard version of ML-KEM. This was once exported as public +// API, but is now internal and only used by libssl. It will be removed entirely +// in the future. +// +// This implements the round-3 specification of Kyber, defined at +// https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf + +// KYBER_public_key contains a Kyber768 public key. The contents of this +// object should never leave the address space since the format is unstable. +struct KYBER_public_key { + union { + uint8_t bytes[512 * (3 + 9) + 32 + 32]; + uint16_t alignment; + } opaque; +}; + +// KYBER_private_key contains a Kyber768 private key. The contents of this +// object should never leave the address space since the format is unstable. +struct KYBER_private_key { + union { + uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32]; + uint16_t alignment; + } opaque; +}; + +// KYBER_PUBLIC_KEY_BYTES is the number of bytes in an encoded Kyber768 public +// key. +#define KYBER_PUBLIC_KEY_BYTES 1184 + +// KYBER_SHARED_SECRET_BYTES is the number of bytes in the Kyber768 shared +// secret. Although the round-3 specification has a variable-length output, the +// final ML-KEM construction is expected to use a fixed 32-byte output. To +// simplify the future transition, we apply the same restriction. +#define KYBER_SHARED_SECRET_BYTES 32 + +// KYBER_generate_key generates a random public/private key pair, writes the +// encoded public key to |out_encoded_public_key| and sets |out_private_key| to +// the private key. +OPENSSL_EXPORT void KYBER_generate_key( + uint8_t out_encoded_public_key[KYBER_PUBLIC_KEY_BYTES], + struct KYBER_private_key *out_private_key); + +// KYBER_public_from_private sets |*out_public_key| to the public key that +// corresponds to |private_key|. (This is faster than parsing the output of +// |KYBER_generate_key| if, for some reason, you need to encapsulate to a key +// that was just generated.) +OPENSSL_EXPORT void KYBER_public_from_private( + struct KYBER_public_key *out_public_key, + const struct KYBER_private_key *private_key); + +// KYBER_CIPHERTEXT_BYTES is number of bytes in the Kyber768 ciphertext. +#define KYBER_CIPHERTEXT_BYTES 1088 + +// KYBER_encap encrypts a random shared secret for |public_key|, writes the +// ciphertext to |out_ciphertext|, and writes the random shared secret to +// |out_shared_secret|. +OPENSSL_EXPORT void KYBER_encap( + uint8_t out_ciphertext[KYBER_CIPHERTEXT_BYTES], + uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES], + const struct KYBER_public_key *public_key); + +// KYBER_decap decrypts a shared secret from |ciphertext| using |private_key| +// and writes it to |out_shared_secret|. If |ciphertext| is invalid, +// |out_shared_secret| is filled with a key that will always be the same for the +// same |ciphertext| and |private_key|, but which appears to be random unless +// one has access to |private_key|. These alternatives occur in constant time. +// Any subsequent symmetric encryption using |out_shared_secret| must use an +// authenticated encryption scheme in order to discover the decapsulation +// failure. +OPENSSL_EXPORT void KYBER_decap( + uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES], + const uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES], + const struct KYBER_private_key *private_key); + + +// Serialisation of keys. + +// KYBER_marshal_public_key serializes |public_key| to |out| in the standard +// format for Kyber public keys. It returns one on success or zero on allocation +// error. +OPENSSL_EXPORT int KYBER_marshal_public_key( + CBB *out, const struct KYBER_public_key *public_key); + +// KYBER_parse_public_key parses a public key, in the format generated by +// |KYBER_marshal_public_key|, from |in| and writes the result to +// |out_public_key|. It returns one on success or zero on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int KYBER_parse_public_key( + struct KYBER_public_key *out_public_key, CBS *in); + +// KYBER_marshal_private_key serializes |private_key| to |out| in the standard +// format for Kyber private keys. It returns one on success or zero on +// allocation error. +OPENSSL_EXPORT int KYBER_marshal_private_key( + CBB *out, const struct KYBER_private_key *private_key); + +// KYBER_PRIVATE_KEY_BYTES is the length of the data produced by +// |KYBER_marshal_private_key|. +#define KYBER_PRIVATE_KEY_BYTES 2400 + +// KYBER_parse_private_key parses a private key, in the format generated by +// |KYBER_marshal_private_key|, from |in| and writes the result to +// |out_private_key|. It returns one on success or zero on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int KYBER_parse_private_key( + struct KYBER_private_key *out_private_key, CBS *in); + + +// Internal symbols. + // KYBER_ENCAP_ENTROPY is the number of bytes of uniformly random entropy // necessary to encapsulate a secret. The entropy will be leaked to the // decapsulating party. diff --git a/Sources/CCryptoBoringSSL/crypto/kyber/kyber.cc b/Sources/CCryptoBoringSSL/crypto/kyber/kyber.cc index 4af369604..581e701f9 100644 --- a/Sources/CCryptoBoringSSL/crypto/kyber/kyber.cc +++ b/Sources/CCryptoBoringSSL/crypto/kyber/kyber.cc @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#define OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER -#include - #include #include diff --git a/Sources/CCryptoBoringSSL/crypto/mldsa/mldsa.cc b/Sources/CCryptoBoringSSL/crypto/mldsa/mldsa.cc index 0e4d847bf..d18fc9ea3 100644 --- a/Sources/CCryptoBoringSSL/crypto/mldsa/mldsa.cc +++ b/Sources/CCryptoBoringSSL/crypto/mldsa/mldsa.cc @@ -28,6 +28,12 @@ static_assert(sizeof(BCM_mldsa87_public_key) == sizeof(MLDSA87_public_key)); static_assert(alignof(BCM_mldsa87_public_key) == alignof(MLDSA87_public_key)); static_assert(sizeof(BCM_mldsa87_prehash) == sizeof(MLDSA87_prehash)); static_assert(alignof(BCM_mldsa87_prehash) == alignof(MLDSA87_prehash)); +static_assert(sizeof(BCM_mldsa44_private_key) == sizeof(MLDSA44_private_key)); +static_assert(alignof(BCM_mldsa44_private_key) == alignof(MLDSA44_private_key)); +static_assert(sizeof(BCM_mldsa44_public_key) == sizeof(MLDSA44_public_key)); +static_assert(alignof(BCM_mldsa44_public_key) == alignof(MLDSA44_public_key)); +static_assert(sizeof(BCM_mldsa44_prehash) == sizeof(MLDSA44_prehash)); +static_assert(alignof(BCM_mldsa44_prehash) == alignof(MLDSA44_prehash)); static_assert(MLDSA_SEED_BYTES == BCM_MLDSA_SEED_BYTES); static_assert(MLDSA_MU_BYTES == BCM_MLDSA_MU_BYTES); static_assert(MLDSA65_PRIVATE_KEY_BYTES == BCM_MLDSA65_PRIVATE_KEY_BYTES); @@ -36,6 +42,9 @@ static_assert(MLDSA65_SIGNATURE_BYTES == BCM_MLDSA65_SIGNATURE_BYTES); static_assert(MLDSA87_PRIVATE_KEY_BYTES == BCM_MLDSA87_PRIVATE_KEY_BYTES); static_assert(MLDSA87_PUBLIC_KEY_BYTES == BCM_MLDSA87_PUBLIC_KEY_BYTES); static_assert(MLDSA87_SIGNATURE_BYTES == BCM_MLDSA87_SIGNATURE_BYTES); +static_assert(MLDSA44_PRIVATE_KEY_BYTES == BCM_MLDSA44_PRIVATE_KEY_BYTES); +static_assert(MLDSA44_PUBLIC_KEY_BYTES == BCM_MLDSA44_PUBLIC_KEY_BYTES); +static_assert(MLDSA44_SIGNATURE_BYTES == BCM_MLDSA44_SIGNATURE_BYTES); int MLDSA65_generate_key( uint8_t out_encoded_public_key[MLDSA65_PUBLIC_KEY_BYTES], @@ -226,3 +235,98 @@ int MLDSA87_parse_public_key(struct MLDSA87_public_key *public_key, CBS *in) { return bcm_success(BCM_mldsa87_parse_public_key( reinterpret_cast(public_key), in)); } + +int MLDSA44_generate_key( + uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[MLDSA_SEED_BYTES], + struct MLDSA44_private_key *out_private_key) { + return bcm_success(BCM_mldsa44_generate_key( + out_encoded_public_key, out_seed, + reinterpret_cast(out_private_key))); +} + +int MLDSA44_private_key_from_seed(struct MLDSA44_private_key *out_private_key, + const uint8_t *seed, size_t seed_len) { + if (seed_len != BCM_MLDSA_SEED_BYTES) { + return 0; + } + return bcm_success(BCM_mldsa44_private_key_from_seed( + reinterpret_cast(out_private_key), seed)); +} + +int MLDSA44_public_from_private(struct MLDSA44_public_key *out_public_key, + const struct MLDSA44_private_key *private_key) { + return bcm_success(BCM_mldsa44_public_from_private( + reinterpret_cast(out_public_key), + reinterpret_cast(private_key))); +} + +int MLDSA44_sign(uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, + const uint8_t *msg, size_t msg_len, const uint8_t *context, + size_t context_len) { + if (context_len > 255) { + return 0; + } + return bcm_success(BCM_mldsa44_sign( + out_encoded_signature, + reinterpret_cast(private_key), msg, + msg_len, context, context_len)); +} + +int MLDSA44_verify(const struct MLDSA44_public_key *public_key, + const uint8_t *signature, size_t signature_len, + const uint8_t *msg, size_t msg_len, const uint8_t *context, + size_t context_len) { + if (context_len > 255 || signature_len != BCM_MLDSA44_SIGNATURE_BYTES) { + return 0; + } + return bcm_success(BCM_mldsa44_verify( + reinterpret_cast(public_key), signature, + msg, msg_len, context, context_len)); +} + +int MLDSA44_prehash_init(struct MLDSA44_prehash *out_state, + const struct MLDSA44_public_key *public_key, + const uint8_t *context, size_t context_len) { + if (context_len > 255) { + return 0; + } + BCM_mldsa44_prehash_init( + reinterpret_cast(out_state), + reinterpret_cast(public_key), context, + context_len); + return 1; +} + +void MLDSA44_prehash_update(struct MLDSA44_prehash *inout_state, + const uint8_t *msg, size_t msg_len) { + BCM_mldsa44_prehash_update( + reinterpret_cast(inout_state), msg, msg_len); +} + +void MLDSA44_prehash_finalize(uint8_t out_msg_rep[MLDSA_MU_BYTES], + struct MLDSA44_prehash *inout_state) { + BCM_mldsa44_prehash_finalize( + out_msg_rep, reinterpret_cast(inout_state)); +} + +int MLDSA44_sign_message_representative( + uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, + const uint8_t msg_rep[MLDSA_MU_BYTES]) { + return bcm_success(BCM_mldsa44_sign_message_representative( + out_encoded_signature, + reinterpret_cast(private_key), msg_rep)); +} + +int MLDSA44_marshal_public_key(CBB *out, + const struct MLDSA44_public_key *public_key) { + return bcm_success(BCM_mldsa44_marshal_public_key( + out, reinterpret_cast(public_key))); +} + +int MLDSA44_parse_public_key(struct MLDSA44_public_key *public_key, CBS *in) { + return bcm_success(BCM_mldsa44_parse_public_key( + reinterpret_cast(public_key), in)); +} diff --git a/Sources/CCryptoBoringSSL/crypto/obj/obj.cc b/Sources/CCryptoBoringSSL/crypto/obj/obj.cc index aba6f2db0..28ef9f0bc 100644 --- a/Sources/CCryptoBoringSSL/crypto/obj/obj.cc +++ b/Sources/CCryptoBoringSSL/crypto/obj/obj.cc @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -173,7 +175,7 @@ int OBJ_obj2nid(const ASN1_OBJECT *obj) { CRYPTO_MUTEX_unlock_read(&global_added_lock); const uint16_t *nid_ptr = reinterpret_cast( - bsearch(obj, kNIDsInOIDOrder, OPENSSL_ARRAY_SIZE(kNIDsInOIDOrder), + bsearch(obj, kNIDsInOIDOrder, std::size(kNIDsInOIDOrder), sizeof(kNIDsInOIDOrder[0]), obj_cmp)); if (nid_ptr == NULL) { return NID_undef; @@ -219,10 +221,9 @@ int OBJ_sn2nid(const char *short_name) { } CRYPTO_MUTEX_unlock_read(&global_added_lock); - const uint16_t *nid_ptr = reinterpret_cast( - bsearch(short_name, kNIDsInShortNameOrder, - OPENSSL_ARRAY_SIZE(kNIDsInShortNameOrder), - sizeof(kNIDsInShortNameOrder[0]), short_name_cmp)); + const uint16_t *nid_ptr = reinterpret_cast(bsearch( + short_name, kNIDsInShortNameOrder, std::size(kNIDsInShortNameOrder), + sizeof(kNIDsInShortNameOrder[0]), short_name_cmp)); if (nid_ptr == NULL) { return NID_undef; } @@ -254,9 +255,9 @@ int OBJ_ln2nid(const char *long_name) { } CRYPTO_MUTEX_unlock_read(&global_added_lock); - const uint16_t *nid_ptr = reinterpret_cast(bsearch( - long_name, kNIDsInLongNameOrder, OPENSSL_ARRAY_SIZE(kNIDsInLongNameOrder), - sizeof(kNIDsInLongNameOrder[0]), long_name_cmp)); + const uint16_t *nid_ptr = reinterpret_cast( + bsearch(long_name, kNIDsInLongNameOrder, std::size(kNIDsInLongNameOrder), + sizeof(kNIDsInLongNameOrder[0]), long_name_cmp)); if (nid_ptr == NULL) { return NID_undef; } diff --git a/Sources/CCryptoBoringSSL/crypto/obj/obj_dat.h b/Sources/CCryptoBoringSSL/crypto/obj/obj_dat.h index a857d535c..344e7f2ea 100644 --- a/Sources/CCryptoBoringSSL/crypto/obj/obj_dat.h +++ b/Sources/CCryptoBoringSSL/crypto/obj/obj_dat.h @@ -15,7 +15,7 @@ // This file is generated by crypto/obj/objects.go. -#define NUM_NID 966 +#define NUM_NID 967 static const uint8_t kObjectData[] = { /* NID_rsadsi */ @@ -8742,6 +8742,7 @@ static const ASN1_OBJECT kObjects[NUM_NID] = { {"X25519Kyber768Draft00", "X25519Kyber768Draft00", NID_X25519Kyber768Draft00, 0, NULL, 0}, {"X25519MLKEM768", "X25519MLKEM768", NID_X25519MLKEM768, 0, NULL, 0}, + {"MLKEM1024", "MLKEM1024", NID_MLKEM1024, 0, NULL, 0}, }; static const uint16_t kNIDsInShortNameOrder[] = { @@ -8864,6 +8865,7 @@ static const uint16_t kNIDsInShortNameOrder[] = { 114 /* MD5-SHA1 */, 95 /* MDC2 */, 911 /* MGF1 */, + 966 /* MLKEM1024 */, 388 /* Mail */, 57 /* Netscape */, 366 /* Nonce */, @@ -9755,6 +9757,7 @@ static const uint16_t kNIDsInLongNameOrder[] = { 647 /* International Organizations */, 142 /* Invalidity Date */, 504 /* MIME MHS */, + 966 /* MLKEM1024 */, 388 /* Mail */, 383 /* Management */, 417 /* Microsoft CSP Name */, diff --git a/Sources/CCryptoBoringSSL/crypto/obj/obj_xref.cc b/Sources/CCryptoBoringSSL/crypto/obj/obj_xref.cc index 5715bb841..7d65724bc 100644 --- a/Sources/CCryptoBoringSSL/crypto/obj/obj_xref.cc +++ b/Sources/CCryptoBoringSSL/crypto/obj/obj_xref.cc @@ -50,13 +50,13 @@ static const nid_triple kTriples[] = { }; int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, int *out_pkey_nid) { - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTriples); i++) { - if (kTriples[i].sign_nid == sign_nid) { + for (const auto &triple : kTriples) { + if (triple.sign_nid == sign_nid) { if (out_digest_nid != NULL) { - *out_digest_nid = kTriples[i].digest_nid; + *out_digest_nid = triple.digest_nid; } if (out_pkey_nid != NULL) { - *out_pkey_nid = kTriples[i].pkey_nid; + *out_pkey_nid = triple.pkey_nid; } return 1; } @@ -66,11 +66,11 @@ int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, int *out_pkey_nid) { } int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, int pkey_nid) { - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTriples); i++) { - if (kTriples[i].digest_nid == digest_nid && - kTriples[i].pkey_nid == pkey_nid) { + for (const auto &triple : kTriples) { + if (triple.digest_nid == digest_nid && + triple.pkey_nid == pkey_nid) { if (out_sign_nid != NULL) { - *out_sign_nid = kTriples[i].sign_nid; + *out_sign_nid = triple.sign_nid; } return 1; } diff --git a/Sources/CCryptoBoringSSL/crypto/pem/pem_all.cc b/Sources/CCryptoBoringSSL/crypto/pem/pem_all.cc index ced7c76b0..832105b72 100644 --- a/Sources/CCryptoBoringSSL/crypto/pem/pem_all.cc +++ b/Sources/CCryptoBoringSSL/crypto/pem/pem_all.cc @@ -38,14 +38,17 @@ IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7) // the relevant private key: this means can handle "traditional" and PKCS#8 // formats transparently. static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) { - RSA *rtmp; if (!key) { - return NULL; + return nullptr; } - rtmp = EVP_PKEY_get1_RSA(key); - EVP_PKEY_free(key); + if (EVP_PKEY_id(key) != EVP_PKEY_RSA) { + // Don't accept RSA-PSS keys in this function. + OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_RSA_KEY); + return nullptr; + } + RSA *rtmp = EVP_PKEY_get1_RSA(key); if (!rtmp) { - return NULL; + return nullptr; } if (rsa) { RSA_free(*rsa); @@ -56,15 +59,13 @@ static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) { RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, void *u) { - EVP_PKEY *pktmp; - pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); - return pkey_get_rsa(pktmp, rsa); + bssl::UniquePtr pkey(PEM_read_bio_PrivateKey(bp, nullptr, cb, u)); + return pkey_get_rsa(pkey.get(), rsa); } RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u) { - EVP_PKEY *pktmp; - pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); - return pkey_get_rsa(pktmp, rsa); + bssl::UniquePtr pkey(PEM_read_PrivateKey(fp, nullptr, cb, u)); + return pkey_get_rsa(pkey.get(), rsa); } IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey) diff --git a/Sources/CCryptoBoringSSL/crypto/pem/pem_info.cc b/Sources/CCryptoBoringSSL/crypto/pem/pem_info.cc index 1ea9b8214..1f80787f7 100644 --- a/Sources/CCryptoBoringSSL/crypto/pem/pem_info.cc +++ b/Sources/CCryptoBoringSSL/crypto/pem/pem_info.cc @@ -143,9 +143,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, for (;;) { if (!PEM_read_bio(bp, &name, &header, &data, &len)) { - uint32_t error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE) { + if (ERR_equals(ERR_peek_last_error(), ERR_LIB_PEM, PEM_R_NO_START_LINE)) { ERR_clear_error(); break; } diff --git a/Sources/CCryptoBoringSSL/crypto/pem/pem_lib.cc b/Sources/CCryptoBoringSSL/crypto/pem/pem_lib.cc index 60aafc1b5..028147a4b 100644 --- a/Sources/CCryptoBoringSSL/crypto/pem/pem_lib.cc +++ b/Sources/CCryptoBoringSSL/crypto/pem/pem_lib.cc @@ -182,9 +182,7 @@ int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, for (;;) { if (!PEM_read_bio(bp, &nm, &header, &data, &len)) { - uint32_t error = ERR_peek_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE) { + if (ERR_equals(ERR_peek_error(), ERR_LIB_PEM, PEM_R_NO_START_LINE)) { ERR_add_error_data(2, "Expecting: ", name); } return 0; diff --git a/Sources/CCryptoBoringSSL/crypto/pkcs8/p5_pbev2.cc b/Sources/CCryptoBoringSSL/crypto/pkcs8/p5_pbev2.cc index d06855706..32a5edf58 100644 --- a/Sources/CCryptoBoringSSL/crypto/pkcs8/p5_pbev2.cc +++ b/Sources/CCryptoBoringSSL/crypto/pkcs8/p5_pbev2.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8.cc b/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8.cc index 0e4f8c581..facc5bb56 100644 --- a/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8.cc +++ b/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8.cc @@ -271,15 +271,15 @@ static const struct pbe_suite kBuiltinPBE[] = { }; static const struct pbe_suite *get_pkcs12_pbe_suite(int pbe_nid) { - for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kBuiltinPBE); i++) { - if (kBuiltinPBE[i].pbe_nid == pbe_nid && + for (const auto &pbe : kBuiltinPBE) { + if (pbe.pbe_nid == pbe_nid && // If |cipher_func| or |md_func| are missing, this is a PBES2 scheme. - kBuiltinPBE[i].cipher_func != NULL && kBuiltinPBE[i].md_func != NULL) { - return &kBuiltinPBE[i]; + pbe.cipher_func != nullptr && pbe.md_func != nullptr) { + return &pbe; } } - return NULL; + return nullptr; } int pkcs12_pbe_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, int alg_nid, @@ -333,9 +333,9 @@ int pkcs8_pbe_decrypt(uint8_t **out, size_t *out_len, CBS *algorithm, goto err; } - for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kBuiltinPBE); i++) { - if (CBS_mem_equal(&obj, kBuiltinPBE[i].oid, kBuiltinPBE[i].oid_len)) { - suite = &kBuiltinPBE[i]; + for (const auto &pbe : kBuiltinPBE) { + if (CBS_mem_equal(&obj, pbe.oid, pbe.oid_len)) { + suite = &pbe; break; } } diff --git a/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8_x509.cc b/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8_x509.cc index 9f4f92a91..19a8bf43d 100644 --- a/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8_x509.cc +++ b/Sources/CCryptoBoringSSL/crypto/pkcs8/pkcs8_x509.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff --git a/Sources/CCryptoBoringSSL/crypto/rand/passive.cc b/Sources/CCryptoBoringSSL/crypto/rand/passive.cc index c74ca369a..c73d0d9a1 100644 --- a/Sources/CCryptoBoringSSL/crypto/rand/passive.cc +++ b/Sources/CCryptoBoringSSL/crypto/rand/passive.cc @@ -38,7 +38,7 @@ static void passive_get_seed_entropy(uint8_t *out_entropy, } #define ENTROPY_READ_LEN \ - (/* last_block size */ 16 + CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD) + (/* last_block size */ 16 + CTR_DRBG_SEED_LEN * BORINGSSL_FIPS_OVERREAD) #if defined(OPENSSL_ANDROID) diff --git a/Sources/CCryptoBoringSSL/crypto/rsa/internal.h b/Sources/CCryptoBoringSSL/crypto/rsa/internal.h index d1702687a..297c90914 100644 --- a/Sources/CCryptoBoringSSL/crypto/rsa/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/rsa/internal.h @@ -28,6 +28,31 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len, size_t param_len, const EVP_MD *md, const EVP_MD *mgf1md); +enum rsa_pss_params_t { + // RSA-PSS using SHA-256, MGF1 with SHA-256, salt length 32. + rsa_pss_sha256, + // RSA-PSS using SHA-384, MGF1 with SHA-384, salt length 48. + rsa_pss_sha384, + // RSA-PSS using SHA-512, MGF1 with SHA-512, salt length 64. + rsa_pss_sha512, +}; + +// rsa_pss_params_get_md returns the hash function used with |params|. This also +// specifies the MGF-1 hash and the salt length because we do not support other +// configurations. +const EVP_MD *rsa_pss_params_get_md(rsa_pss_params_t params); + +// rsa_marshal_pss_params marshals |params| as a DER-encoded RSASSA-PSS-params +// (RFC 4055). It returns one on success and zero on error. +int rsa_marshal_pss_params(CBB *cbb, rsa_pss_params_t params); + +// rsa_marshal_pss_params decodes a DER-encoded RSASSA-PSS-params +// (RFC 4055). It returns one on success and zero on error. On success, it sets +// |*out| to the result. If |allow_explicit_trailer| is non-zero, an explicit +// encoding of the trailerField is allowed, although it is not valid DER. +int rsa_parse_pss_params(CBS *cbs, rsa_pss_params_t *out, + int allow_explicit_trailer); + #if defined(__cplusplus) } // extern C diff --git a/Sources/CCryptoBoringSSL/crypto/rsa/rsa_asn1.cc b/Sources/CCryptoBoringSSL/crypto/rsa/rsa_asn1.cc index 3f66fd77d..f01ed4a3b 100644 --- a/Sources/CCryptoBoringSSL/crypto/rsa/rsa_asn1.cc +++ b/Sources/CCryptoBoringSSL/crypto/rsa/rsa_asn1.cc @@ -20,12 +20,17 @@ #include #include +#include #include #include +#include +#include +#include -#include "../fipsmodule/rsa/internal.h" #include "../bytestring/internal.h" +#include "../fipsmodule/rsa/internal.h" #include "../internal.h" +#include "internal.h" static int parse_integer(CBS *cbs, BIGNUM **out) { @@ -109,7 +114,7 @@ int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, } // kVersionTwoPrime is the value of the version field for a two-prime -// RSAPrivateKey structure (RFC 3447). +// RSAPrivateKey structure (RFC 8017). static const uint64_t kVersionTwoPrime = 0; RSA *RSA_parse_private_key(CBS *cbs) { @@ -205,59 +210,23 @@ int RSA_private_key_to_bytes(uint8_t **out_bytes, size_t *out_len, } RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - RSA *ret = RSA_parse_public_key(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - RSA_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, RSA_parse_public_key); } int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !RSA_marshal_public_key(&cbb, in)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/256, outp, + [&](CBB *cbb) -> bool { return RSA_marshal_public_key(cbb, in); }); } RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) { - if (len < 0) { - return NULL; - } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - RSA *ret = RSA_parse_private_key(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - RSA_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + return bssl::D2IFromCBS(out, inp, len, RSA_parse_private_key); } int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) { - CBB cbb; - if (!CBB_init(&cbb, 0) || - !RSA_marshal_private_key(&cbb, in)) { - CBB_cleanup(&cbb); - return -1; - } - return CBB_finish_i2d(&cbb, outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/512, outp, + [&](CBB *cbb) -> bool { return RSA_marshal_private_key(cbb, in); }); } RSA *RSAPublicKey_dup(const RSA *rsa) { @@ -281,3 +250,146 @@ RSA *RSAPrivateKey_dup(const RSA *rsa) { OPENSSL_free(der); return ret; } + +static const uint8_t kPSSParamsSHA256[] = { + 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, + 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20}; + +static const uint8_t kPSSParamsSHA384[] = { + 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa1, 0x1c, 0x30, + 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x02, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x30}; + +static const uint8_t kPSSParamsSHA512[] = { + 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa1, 0x1c, 0x30, + 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x40}; + +const EVP_MD *rsa_pss_params_get_md(rsa_pss_params_t params) { + switch (params) { + case rsa_pss_sha256: + return EVP_sha256(); + case rsa_pss_sha384: + return EVP_sha384(); + case rsa_pss_sha512: + return EVP_sha512(); + } + abort(); +} + +int rsa_marshal_pss_params(CBB *cbb, rsa_pss_params_t params) { + bssl::Span bytes; + switch (params) { + case rsa_pss_sha256: + bytes = kPSSParamsSHA256; + break; + case rsa_pss_sha384: + bytes = kPSSParamsSHA384; + break; + case rsa_pss_sha512: + bytes = kPSSParamsSHA512; + break; + } + + return CBB_add_bytes(cbb, bytes.data(), bytes.size()); +} + +// 1.2.840.113549.1.1.8 +static const uint8_t kMGF1OID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x08}; + +int rsa_parse_pss_params(CBS *cbs, rsa_pss_params_t *out, + int allow_explicit_trailer) { + // See RFC 4055, section 3.1. + // + // hashAlgorithm, maskGenAlgorithm, and saltLength all have DEFAULTs + // corresponding to SHA-1. We do not support SHA-1 with PSS, so we do not + // bother recognizing the omitted versions. + CBS params, hash_wrapper, mask_wrapper, mask_alg, mask_oid, salt_wrapper; + uint64_t salt_len; + if (!CBS_get_asn1(cbs, ¶ms, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(¶ms, &hash_wrapper, + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) || + // |hash_wrapper| will be parsed below. + !CBS_get_asn1(¶ms, &mask_wrapper, + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1) || + !CBS_get_asn1(&mask_wrapper, &mask_alg, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1(&mask_alg, &mask_oid, CBS_ASN1_OBJECT) || + // We only support MGF-1. + bssl::Span(mask_oid) != kMGF1OID || + // The remainder of |mask_alg| will be parsed below. + CBS_len(&mask_wrapper) != 0 || + !CBS_get_asn1(¶ms, &salt_wrapper, + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2) || + !CBS_get_asn1_uint64(&salt_wrapper, &salt_len) || + CBS_len(&salt_wrapper) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + return 0; + } + + // The trailer field must be 1 (0xbc). This value is DEFAULT, so the structure + // is required to omit it in DER. + if (CBS_len(¶ms) != 0 && allow_explicit_trailer) { + CBS trailer_wrapper; + uint64_t trailer; + if (!CBS_get_asn1(¶ms, &trailer_wrapper, + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3) || + !CBS_get_asn1_uint64(&trailer_wrapper, &trailer) || // + trailer != 1) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + return 0; + } + } + if (CBS_len(¶ms) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + return 0; + } + + int hash_nid = EVP_parse_digest_algorithm_nid(&hash_wrapper); + if (hash_nid == NID_undef || CBS_len(&hash_wrapper) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + return 0; + } + + // We only support combinations where the MGF-1 hash matches the overall hash. + int mgf1_hash_nid = EVP_parse_digest_algorithm_nid(&mask_alg); + if (mgf1_hash_nid != hash_nid || CBS_len(&mask_alg) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + return 0; + } + + // We only support salt lengths that match the hash length. + rsa_pss_params_t ret; + uint64_t hash_len; + switch (hash_nid) { + case NID_sha256: + ret = rsa_pss_sha256; + hash_len = 32; + break; + case NID_sha384: + ret = rsa_pss_sha384; + hash_len = 48; + break; + case NID_sha512: + ret = rsa_pss_sha512; + hash_len = 64; + break; + default: + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + return 0; + } + if (salt_len != hash_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING); + return 0; + } + + *out = ret; + return 1; +} diff --git a/Sources/CCryptoBoringSSL/crypto/rsa/rsa_extra.cc b/Sources/CCryptoBoringSSL/crypto/rsa/rsa_extra.cc index f7f9bbbb7..64009a333 100644 --- a/Sources/CCryptoBoringSSL/crypto/rsa/rsa_extra.cc +++ b/Sources/CCryptoBoringSSL/crypto/rsa/rsa_extra.cc @@ -17,3 +17,14 @@ int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) { return 1; } void RSA_blinding_off(RSA *rsa) {} + +const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *rsa) { + // We do not currently implement this function. By default, we will not parse + // |EVP_PKEY_RSA_PSS|. Callers that opt in with a BoringSSL-specific API are + // currently assumed to not need this function. Callers that need that opt-in + // and this functionality should contact the BoringSSL team. + // + // If we do add support later, the |maskHash| field should be filled in for + // OpenSSL compatibility. + return nullptr; +} diff --git a/Sources/CCryptoBoringSSL/crypto/sha/sha256.cc b/Sources/CCryptoBoringSSL/crypto/sha/sha256.cc index 7d2f14629..85ecd0e99 100644 --- a/Sources/CCryptoBoringSSL/crypto/sha/sha256.cc +++ b/Sources/CCryptoBoringSSL/crypto/sha/sha256.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include #include diff --git a/Sources/CCryptoBoringSSL/crypto/sha/sha512.cc b/Sources/CCryptoBoringSSL/crypto/sha/sha512.cc index cd138db20..58702fc68 100644 --- a/Sources/CCryptoBoringSSL/crypto/sha/sha512.cc +++ b/Sources/CCryptoBoringSSL/crypto/sha/sha512.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include #include diff --git a/Sources/CCryptoBoringSSL/crypto/spake2plus/internal.h b/Sources/CCryptoBoringSSL/crypto/spake2plus/internal.h index 3d462cffc..69cf97ba6 100644 --- a/Sources/CCryptoBoringSSL/crypto/spake2plus/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/spake2plus/internal.h @@ -19,7 +19,7 @@ #include -#include +#include #include #include "../fipsmodule/ec/internal.h" diff --git a/Sources/CCryptoBoringSSL/crypto/spake2plus/spake2plus.cc b/Sources/CCryptoBoringSSL/crypto/spake2plus/spake2plus.cc index 83e31b272..def70f5cf 100644 --- a/Sources/CCryptoBoringSSL/crypto/spake2plus/spake2plus.cc +++ b/Sources/CCryptoBoringSSL/crypto/spake2plus/spake2plus.cc @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "../fipsmodule/bn/internal.h" #include "../fipsmodule/ec/internal.h" diff --git a/Sources/CCryptoBoringSSL/crypto/trust_token/pmbtoken.cc b/Sources/CCryptoBoringSSL/crypto/trust_token/pmbtoken.cc index 47328b602..ff0fcf2a9 100644 --- a/Sources/CCryptoBoringSSL/crypto/trust_token/pmbtoken.cc +++ b/Sources/CCryptoBoringSSL/crypto/trust_token/pmbtoken.cc @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "../ec/internal.h" #include "../fipsmodule/bn/internal.h" @@ -196,13 +196,13 @@ static int pmbtoken_compute_keys(const PMBTOKEN_METHOD *method, const EC_SCALAR *scalars[] = {x0, y0, x1, y1, xs, ys}; size_t scalar_len = BN_num_bytes(EC_GROUP_get0_order(group)); - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) { + for (const EC_SCALAR *scalar : scalars) { uint8_t *buf; if (!CBB_add_space(out_private, &buf, scalar_len)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); return 0; } - ec_scalar_to_bytes(group, buf, &scalar_len, scalars[i]); + ec_scalar_to_bytes(group, buf, &scalar_len, scalar); } EC_AFFINE pub_affine[3]; @@ -287,10 +287,9 @@ static int pmbtoken_issuer_key_from_bytes(const PMBTOKEN_METHOD *method, size_t scalar_len = BN_num_bytes(EC_GROUP_get0_order(group)); EC_SCALAR *scalars[] = {&key->x0, &key->y0, &key->x1, &key->y1, &key->xs, &key->ys}; - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(scalars); i++) { + for (EC_SCALAR *scalar : scalars) { if (!CBS_get_bytes(&cbs, &tmp, scalar_len) || - !ec_scalar_from_bytes(group, scalars[i], CBS_data(&tmp), - CBS_len(&tmp))) { + !ec_scalar_from_bytes(group, scalar, CBS_data(&tmp), CBS_len(&tmp))) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE); return 0; } diff --git a/Sources/CCryptoBoringSSL/crypto/trust_token/trust_token.cc b/Sources/CCryptoBoringSSL/crypto/trust_token/trust_token.cc index 3d2ef5219..b4cd9a165 100644 --- a/Sources/CCryptoBoringSSL/crypto/trust_token/trust_token.cc +++ b/Sources/CCryptoBoringSSL/crypto/trust_token/trust_token.cc @@ -12,12 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + +#include + #include #include #include #include -#include -#include +#include #include "internal.h" @@ -226,7 +229,7 @@ void TRUST_TOKEN_CLIENT_free(TRUST_TOKEN_CLIENT *ctx) { int TRUST_TOKEN_CLIENT_add_key(TRUST_TOKEN_CLIENT *ctx, size_t *out_key_index, const uint8_t *key, size_t key_len) { - if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys) || + if (ctx->num_keys == std::size(ctx->keys) || ctx->num_keys >= ctx->method->max_keys) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS); return 0; @@ -462,7 +465,7 @@ void TRUST_TOKEN_ISSUER_free(TRUST_TOKEN_ISSUER *ctx) { int TRUST_TOKEN_ISSUER_add_key(TRUST_TOKEN_ISSUER *ctx, const uint8_t *key, size_t key_len) { - if (ctx->num_keys == OPENSSL_ARRAY_SIZE(ctx->keys) || + if (ctx->num_keys == std::size(ctx->keys) || ctx->num_keys >= ctx->method->max_keys) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_TOO_MANY_KEYS); return 0; diff --git a/Sources/CCryptoBoringSSL/crypto/trust_token/voprf.cc b/Sources/CCryptoBoringSSL/crypto/trust_token/voprf.cc index 7e68d9e71..c91e390b4 100644 --- a/Sources/CCryptoBoringSSL/crypto/trust_token/voprf.cc +++ b/Sources/CCryptoBoringSSL/crypto/trust_token/voprf.cc @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "../ec/internal.h" #include "../fipsmodule/ec/internal.h" diff --git a/Sources/CCryptoBoringSSL/crypto/x509/a_sign.cc b/Sources/CCryptoBoringSSL/crypto/x509/a_sign.cc index 9004fb431..55c8d790a 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/a_sign.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/a_sign.cc @@ -18,12 +18,16 @@ #include #include #include +#include #include #include +#include "../internal.h" +#include "../mem_internal.h" #include "internal.h" + int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey, const EVP_MD *type) { @@ -41,55 +45,56 @@ int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) { - int ret = 0; - uint8_t *in = NULL, *out = NULL; - - { - if (signature->type != V_ASN1_BIT_STRING) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); - goto err; - } + // Historically, this function called |EVP_MD_CTX_cleanup| on return. Some + // callers rely on this to avoid memory leaks. + bssl::Cleanup cleanup = [&] { EVP_MD_CTX_cleanup(ctx); }; - // Write out the requested copies of the AlgorithmIdentifier. - if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) { - goto err; - } - if (algor2 && !x509_digest_sign_algorithm(ctx, algor2)) { - goto err; - } + // Write out the requested copies of the AlgorithmIdentifier. This may modify + // |asn|, so we must do it first. + if ((algor1 != nullptr && !x509_digest_sign_algorithm(ctx, algor1)) || + (algor2 != nullptr && !x509_digest_sign_algorithm(ctx, algor2))) { + return 0; + } - int in_len = ASN1_item_i2d(reinterpret_cast(asn), &in, it); - if (in_len < 0) { - goto err; - } + uint8_t *in = nullptr; + int in_len = ASN1_item_i2d(reinterpret_cast(asn), &in, it); + if (in_len < 0) { + return 0; + } + bssl::UniquePtr free_in(in); - EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); - size_t out_len = EVP_PKEY_size(pkey); - if (out_len > INT_MAX) { - OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW); - goto err; - } + return x509_sign_to_bit_string(ctx, signature, bssl::Span(in, in_len)); +} - out = reinterpret_cast(OPENSSL_malloc(out_len)); - if (out == NULL) { - goto err; - } +int x509_sign_to_bit_string(EVP_MD_CTX *ctx, ASN1_BIT_STRING *out, + bssl::Span in) { + if (out->type != V_ASN1_BIT_STRING) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); + return 0; + } - if (!EVP_DigestSign(ctx, out, &out_len, in, in_len)) { - OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); - goto err; - } + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx); + size_t sig_len = EVP_PKEY_size(pkey); + if (sig_len > INT_MAX) { + // Ensure the signature will fit in |out|. + OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW); + return 0; + } + bssl::Array sig; + if (!sig.Init(sig_len)) { + return 0; + } - ASN1_STRING_set0(signature, out, (int)out_len); - out = NULL; - signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; - ret = (int)out_len; + if (!EVP_DigestSign(ctx, sig.data(), &sig_len, in.data(), in.size())) { + OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); + return 0; } + sig.Shrink(sig_len); -err: - EVP_MD_CTX_cleanup(ctx); - OPENSSL_free(in); - OPENSSL_free(out); - return ret; + uint8_t *sig_data; + sig.Release(&sig_data, &sig_len); + ASN1_STRING_set0(out, sig_data, static_cast(sig_len)); + out->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + out->flags |= ASN1_STRING_FLAG_BITS_LEFT; + return static_cast(sig_len); } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/a_verify.cc b/Sources/CCryptoBoringSSL/crypto/x509/a_verify.cc index 0e15194b8..5b5f881d3 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/a_verify.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/a_verify.cc @@ -17,18 +17,21 @@ #include #include +#include #include #include #include #include #include #include +#include #include "internal.h" -int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *a, - const ASN1_BIT_STRING *signature, void *asn, - EVP_PKEY *pkey) { + +int x509_verify_signature(const X509_ALGOR *sigalg, + const ASN1_BIT_STRING *signature, + bssl::Span in, EVP_PKEY *pkey) { if (!pkey) { OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); return 0; @@ -41,34 +44,29 @@ int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *a, return 0; } } else { - sig_len = (size_t)ASN1_STRING_length(signature); - } - - EVP_MD_CTX ctx; - uint8_t *buf_in = NULL; - int ret = 0, inl = 0; - EVP_MD_CTX_init(&ctx); - - if (!x509_digest_verify_init(&ctx, a, pkey)) { - goto err; + sig_len = static_cast(ASN1_STRING_length(signature)); } - inl = ASN1_item_i2d(reinterpret_cast(asn), &buf_in, it); - - if (buf_in == NULL) { - goto err; + bssl::ScopedEVP_MD_CTX ctx; + if (!x509_digest_verify_init(ctx.get(), sigalg, pkey)) { + return 0; } - - if (!EVP_DigestVerify(&ctx, ASN1_STRING_get0_data(signature), sig_len, buf_in, - inl)) { + if (!EVP_DigestVerify(ctx.get(), ASN1_STRING_get0_data(signature), sig_len, + in.data(), in.size())) { OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB); - goto err; + return 0; } + return 1; +} - ret = 1; - -err: - OPENSSL_free(buf_in); - EVP_MD_CTX_cleanup(&ctx); - return ret; +int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *sigalg, + const ASN1_BIT_STRING *signature, void *asn, + EVP_PKEY *pkey) { + uint8_t *in = nullptr; + int in_len = ASN1_item_i2d(reinterpret_cast(asn), &in, it); + if (in_len < 0) { + return 0; + } + bssl::UniquePtr free_in(in); + return x509_verify_signature(sigalg, signature, bssl::Span(in, in_len), pkey); } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/algorithm.cc b/Sources/CCryptoBoringSSL/crypto/x509/algorithm.cc index ff68574ab..602d1b675 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/algorithm.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/algorithm.cc @@ -22,6 +22,12 @@ #include "internal.h" + +// TODO(crbug.com/42290422): Rewrite this logic to recognize signature +// algorithms without pulling in the OID table. We can enumerate every supported +// signature algorithm into a small enum and convert them to/from |EVP_PKEY_CTX| +// and |X509_ALGOR|. + // Restrict the digests that are allowed in X509 certificates static int x509_digest_nid_ok(const int digest_nid) { switch (digest_nid) { @@ -39,7 +45,8 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) { return 0; } - if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA || + EVP_PKEY_id(pkey) == EVP_PKEY_RSA_PSS) { int pad_mode; if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) { return 0; @@ -88,7 +95,10 @@ int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, } // Check the public key OID matches the public key type. - if (pkey_nid != EVP_PKEY_id(pkey)) { + const bool pkey_matches = + pkey_nid == EVP_PKEY_id(pkey) || + (sigalg_nid == NID_rsassaPss && EVP_PKEY_id(pkey) == EVP_PKEY_RSA_PSS); + if (!pkey_matches) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE); return 0; } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/asn1_gen.cc b/Sources/CCryptoBoringSSL/crypto/x509/asn1_gen.cc index 8375f27cc..edec46633 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/asn1_gen.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/asn1_gen.cc @@ -299,9 +299,9 @@ static int generate_v3(CBB *cbb, const char *str, const X509V3_CTX *cnf, {"SET", CBS_ASN1_SET}, }; CBS_ASN1_TAG type = 0; - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTypes); i++) { - if (cbs_str_equal(&name, kTypes[i].name)) { - type = kTypes[i].type; + for (const auto &t : kTypes) { + if (cbs_str_equal(&name, t.name)) { + type = t.type; break; } } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/by_file.cc b/Sources/CCryptoBoringSSL/crypto/x509/by_file.cc index 491d60b4e..3916fa568 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/by_file.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/by_file.cc @@ -70,9 +70,9 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) { for (;;) { x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); if (x == NULL) { - uint32_t error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE && count > 0) { + if (ERR_equals(ERR_peek_last_error(), ERR_LIB_PEM, + PEM_R_NO_START_LINE) && + count > 0) { ERR_clear_error(); break; } @@ -131,9 +131,9 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) { for (;;) { x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); if (x == NULL) { - uint32_t error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) == ERR_LIB_PEM && - ERR_GET_REASON(error) == PEM_R_NO_START_LINE && count > 0) { + if (ERR_equals(ERR_peek_last_error(), ERR_LIB_PEM, + PEM_R_NO_START_LINE) && + count > 0) { ERR_clear_error(); break; } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/internal.h b/Sources/CCryptoBoringSSL/crypto/x509/internal.h index 955143afb..a4f3be1ee 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/internal.h +++ b/Sources/CCryptoBoringSSL/crypto/x509/internal.h @@ -17,6 +17,7 @@ #include #include +#include #include #include "../asn1/internal.h" @@ -29,21 +30,24 @@ extern "C" { // Internal structures. -typedef struct X509_val_st { - ASN1_TIME *notBefore; - ASN1_TIME *notAfter; -} X509_VAL; - -DECLARE_ASN1_FUNCTIONS_const(X509_VAL) - struct X509_pubkey_st { - X509_ALGOR *algor; - ASN1_BIT_STRING *public_key; + X509_ALGOR algor; + ASN1_BIT_STRING public_key; EVP_PKEY *pkey; } /* X509_PUBKEY */; +void x509_pubkey_init(X509_PUBKEY *key); +void x509_pubkey_cleanup(X509_PUBKEY *key); + +int x509_parse_public_key(CBS *cbs, X509_PUBKEY *out, + bssl::Span algs); +int x509_marshal_public_key(CBB *cbb, const X509_PUBKEY *in); +int x509_pubkey_set1(X509_PUBKEY *key, EVP_PKEY *pkey); + // X509_PUBKEY is an |ASN1_ITEM| whose ASN.1 type is SubjectPublicKeyInfo and C // type is |X509_PUBKEY*|. +// TODO(crbug.com/42290417): Remove this when |X509| and |X509_REQ| no longer +// depend on the tables. DECLARE_ASN1_ITEM(X509_PUBKEY) struct X509_name_entry_st { @@ -97,28 +101,31 @@ DECLARE_ASN1_ITEM(X509_EXTENSION) // (RFC 5280) and C type is |STACK_OF(X509_EXTENSION)*|. DECLARE_ASN1_ITEM(X509_EXTENSIONS) -typedef struct { - ASN1_INTEGER *version; // [ 0 ] default of v1 - ASN1_INTEGER *serialNumber; - X509_ALGOR *signature; +struct x509_st { + // TBSCertificate fields: + uint8_t version; // One of the |X509_VERSION_*| constants. + ASN1_INTEGER serialNumber; + X509_ALGOR tbs_sig_alg; + // TODO(crbug.com/42290417): When |X509_NAME| no longer uses the macro system, + // try to embed this struct. X509_NAME *issuer; - X509_VAL *validity; + ASN1_TIME notBefore; + ASN1_TIME notAfter; + // TODO(crbug.com/42290417): When |X509_NAME| no longer uses the macro system, + // try to embed this struct. X509_NAME *subject; - X509_PUBKEY *key; + X509_PUBKEY key; ASN1_BIT_STRING *issuerUID; // [ 1 ] optional in v2 ASN1_BIT_STRING *subjectUID; // [ 2 ] optional in v2 STACK_OF(X509_EXTENSION) *extensions; // [ 3 ] optional in v3 - ASN1_ENCODING enc; -} X509_CINF; - -// TODO(https://crbug.com/boringssl/407): This is not const because it contains -// an |X509_NAME|. -DECLARE_ASN1_FUNCTIONS(X509_CINF) - -struct x509_st { - X509_CINF *cert_info; - X509_ALGOR *sig_alg; - ASN1_BIT_STRING *signature; + // Certificate fields: + X509_ALGOR sig_alg; + ASN1_BIT_STRING signature; + // Other state: + // buf, if not nullptr, contains a copy of the serialized Certificate. + // TODO(davidben): Now every parsed |X509| has an underlying |CRYPTO_BUFFER|, + // but |X509|s created peacemeal do not. Can we make this more uniform? + CRYPTO_BUFFER *buf; CRYPTO_refcount_t references; CRYPTO_EX_DATA ex_data; // These contain copies of various extension values @@ -136,6 +143,8 @@ struct x509_st { CRYPTO_MUTEX lock; } /* X509 */; +int x509_marshal_tbs_cert(CBB *cbb, X509 *x509); + // X509 is an |ASN1_ITEM| whose ASN.1 type is X.509 Certificate (RFC 5280) and C // type is |X509*|. DECLARE_ASN1_ITEM(X509) @@ -385,6 +394,17 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor); int x509_digest_verify_init(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, EVP_PKEY *pkey); +// x509_verify_signature verifies a |signature| using |sigalg| and |pkey| over +// |in|. It returns one if the signature is valid and zero on error. +int x509_verify_signature(const X509_ALGOR *sigalg, + const ASN1_BIT_STRING *signature, + bssl::Span in, EVP_PKEY *pkey); + +// x509_sign_to_bit_string signs |in| using |ctx| and saves the result in |out|. +// It returns the length of the signature on success and zero on error. +int x509_sign_to_bit_string(EVP_MD_CTX *ctx, ASN1_BIT_STRING *out, + bssl::Span in); + // Path-building functions. @@ -555,6 +575,13 @@ int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname); // mutated. int x509_marshal_name(CBB *out, X509_NAME *in); +void x509_algor_init(X509_ALGOR *alg); +void x509_algor_cleanup(X509_ALGOR *alg); + +// x509_parse_algorithm parses a DER-encoded, AlgorithmIdentifier from |cbs| and +// writes the result to |*out|. It returns one on success and zero on error. +int x509_parse_algorithm(CBS *cbs, X509_ALGOR *out); + // x509_marshal_algorithm marshals |in| as a DER-encoded, AlgorithmIdentifier // and writes the result to |out|. It returns one on success and zero on error. int x509_marshal_algorithm(CBB *out, const X509_ALGOR *in); diff --git a/Sources/CCryptoBoringSSL/crypto/x509/rsa_pss.cc b/Sources/CCryptoBoringSSL/crypto/x509/rsa_pss.cc index 663476480..395e210d3 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/rsa_pss.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/rsa_pss.cc @@ -19,11 +19,14 @@ #include #include +#include #include #include #include #include +#include +#include "../rsa/internal.h" #include "internal.h" @@ -46,111 +49,18 @@ ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = { IMPLEMENT_ASN1_FUNCTIONS_const(RSA_PSS_PARAMS) -// Given an MGF1 Algorithm ID decode to an Algorithm Identifier -static X509_ALGOR *rsa_mgf1_decode(const X509_ALGOR *alg) { - if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 || alg->parameter == NULL || - alg->parameter->type != V_ASN1_SEQUENCE) { - return NULL; - } - - const uint8_t *p = alg->parameter->value.sequence->data; - int plen = alg->parameter->value.sequence->length; - return d2i_X509_ALGOR(NULL, &p, plen); -} - -static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg) { - if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) { - return NULL; - } - - const uint8_t *p = alg->parameter->value.sequence->data; - int plen = alg->parameter->value.sequence->length; - return d2i_RSA_PSS_PARAMS(NULL, &p, plen); -} - -static int is_allowed_pss_md(const EVP_MD *md) { - int md_type = EVP_MD_type(md); - return md_type == NID_sha256 || md_type == NID_sha384 || - md_type == NID_sha512; -} - -// rsa_md_to_algor sets |*palg| to an |X509_ALGOR| describing the digest |md|, -// which must be an allowed PSS digest. -static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) { - // SHA-1 should be omitted (DEFAULT), but we do not allow SHA-1. - assert(is_allowed_pss_md(md)); - *palg = X509_ALGOR_new(); - if (*palg == NULL) { +static int rsa_pss_decode(const X509_ALGOR *alg, rsa_pss_params_t *out) { + if (alg->parameter == nullptr || alg->parameter->type != V_ASN1_SEQUENCE) { return 0; } - if (!X509_ALGOR_set_md(*palg, md)) { - X509_ALGOR_free(*palg); - *palg = NULL; - return 0; - } - return 1; -} - -// rsa_md_to_mgf1 sets |*palg| to an |X509_ALGOR| describing MGF-1 with the -// digest |mgf1md|, which must be an allowed PSS digest. -static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) { - // SHA-1 should be omitted (DEFAULT), but we do not allow SHA-1. - assert(is_allowed_pss_md(mgf1md)); - X509_ALGOR *algtmp = NULL; - ASN1_STRING *stmp = NULL; - // need to embed algorithm ID inside another - if (!rsa_md_to_algor(&algtmp, mgf1md) || - !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) { - goto err; - } - *palg = X509_ALGOR_new(); - if (!*palg) { - goto err; - } - if (!X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp)) { - goto err; - } - stmp = NULL; - -err: - ASN1_STRING_free(stmp); - X509_ALGOR_free(algtmp); - if (*palg) { - return 1; - } - return 0; -} - -static const EVP_MD *rsa_algor_to_md(const X509_ALGOR *alg) { - if (!alg) { - // If omitted, PSS defaults to SHA-1, which we do not allow. - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - return NULL; - } - const EVP_MD *md = EVP_get_digestbyobj(alg->algorithm); - if (md == NULL || !is_allowed_pss_md(md)) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - return NULL; - } - return md; -} - -static const EVP_MD *rsa_mgf1_to_md(const X509_ALGOR *alg) { - if (!alg) { - // If omitted, PSS defaults to MGF-1 with SHA-1, which we do not allow. - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - return NULL; - } - // Check mask and lookup mask hash algorithm. - X509_ALGOR *maskHash = rsa_mgf1_decode(alg); - if (maskHash == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - return NULL; - } - const EVP_MD *ret = rsa_algor_to_md(maskHash); - X509_ALGOR_free(maskHash); - return ret; + // Although a syntax error in DER, we tolerate an explicitly-encoded trailer. + // See the certificates in cl/362617931. + CBS cbs; + CBS_init(&cbs, alg->parameter->value.sequence->data, + alg->parameter->value.sequence->length); + return rsa_parse_pss_params(&cbs, out, /*allow_explicit_trailer=*/true) && + CBS_len(&cbs) == 0; } int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) { @@ -162,203 +72,111 @@ int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) { return 0; } - if (sigmd != mgf1md || !is_allowed_pss_md(sigmd)) { + if (sigmd != mgf1md) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); return 0; } int md_len = (int)EVP_MD_size(sigmd); - if (saltlen == -1) { - saltlen = md_len; - } else if (saltlen != md_len) { + if (saltlen != RSA_PSS_SALTLEN_DIGEST && saltlen != md_len) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); return 0; } - int ret = 0; - ASN1_STRING *os = NULL; - RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new(); - if (!pss) { - goto err; - } - - // The DEFAULT value is 20, but this does not match any supported digest. - assert(saltlen != 20); - pss->saltLength = ASN1_INTEGER_new(); - if (!pss->saltLength || // - !ASN1_INTEGER_set_int64(pss->saltLength, saltlen)) { - goto err; + rsa_pss_params_t params; + switch (EVP_MD_type(sigmd)) { + case NID_sha256: + params = rsa_pss_sha256; + break; + case NID_sha384: + params = rsa_pss_sha384; + break; + case NID_sha512: + params = rsa_pss_sha512; + break; + default: + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + return 0; } - if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) || - !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) { - goto err; + // Encode |params| to an |ASN1_STRING|. + uint8_t buf[128]; // The largest param fits comfortably in 128 bytes. + CBB cbb; + CBB_init_fixed(&cbb, buf, sizeof(buf)); + if (!rsa_marshal_pss_params(&cbb, params)) { + return 0; } - - // Finally create string with pss parameter encoding. - if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) { - goto err; + bssl::UniquePtr params_str( + ASN1_STRING_type_new(V_ASN1_SEQUENCE)); + if (params_str == nullptr || + !ASN1_STRING_set(params_str.get(), CBB_data(&cbb), CBB_len(&cbb))) { + return 0; } if (!X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, - os)) { - goto err; + params_str.get())) { + return 0; } - os = NULL; - ret = 1; - -err: - RSA_PSS_PARAMS_free(pss); - ASN1_STRING_free(os); - return ret; + params_str.release(); // |X509_ALGOR_set0| took ownership. + return 1; } int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, EVP_PKEY *pkey) { assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); + rsa_pss_params_t params; + if (!rsa_pss_decode(sigalg, ¶ms)) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); + return 0; + } - // Decode PSS parameters - int ret = 0; - RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg); - - { - if (pss == NULL) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - goto err; - } - - const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm); - const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm); - if (mgf1md == NULL || md == NULL) { - goto err; - } - - // We require the MGF-1 and signing hashes to match. - if (mgf1md != md) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - goto err; - } - - // We require the salt length be the hash length. The DEFAULT value is 20, - // but this does not match any supported salt length. - uint64_t salt_len = 0; - if (pss->saltLength == NULL || - !ASN1_INTEGER_get_uint64(&salt_len, pss->saltLength) || - salt_len != EVP_MD_size(md)) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - goto err; - } - assert(salt_len <= INT_MAX); - - // The trailer field must be 1 (0xbc). This value is DEFAULT, so the - // structure is required to omit it in DER. Although a syntax error, we also - // tolerate an explicitly-encoded value. See the certificates in - // cl/362617931. - if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); - goto err; - } - - EVP_PKEY_CTX *pctx; - if (!EVP_DigestVerifyInit(ctx, &pctx, md, NULL, pkey) || - !EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || - !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, (int)salt_len) || - !EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md)) { - goto err; - } - - ret = 1; + const EVP_MD *md = rsa_pss_params_get_md(params); + EVP_PKEY_CTX *pctx; + if (!EVP_DigestVerifyInit(ctx, &pctx, md, nullptr, pkey) || + !EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) || + !EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, md)) { + return 0; } -err: - RSA_PSS_PARAMS_free(pss); - return ret; + return 1; } int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, ASN1_PCTX *pctx) { assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); - - int rv = 0; - X509_ALGOR *maskHash = NULL; - RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg); - if (!pss) { - if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) { - goto err; - } - rv = 1; - goto err; + rsa_pss_params_t params; + if (!rsa_pss_decode(sigalg, ¶ms)) { + return BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0; + } + + const char *hash_str = nullptr; + uint32_t salt_len = 0; + switch (params) { + case rsa_pss_sha256: + hash_str = "sha256"; + salt_len = 32; + break; + case rsa_pss_sha384: + hash_str = "sha384"; + salt_len = 48; + break; + case rsa_pss_sha512: + hash_str = "sha512"; + salt_len = 64; + break; } if (BIO_puts(bp, "\n") <= 0 || // !BIO_indent(bp, indent, 128) || // - BIO_puts(bp, "Hash Algorithm: ") <= 0) { - goto err; - } - - if (pss->hashAlgorithm) { - if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) { - goto err; - } - } else if (BIO_puts(bp, "sha1 (default)") <= 0) { - goto err; - } - - if (BIO_puts(bp, "\n") <= 0 || // + BIO_printf(bp, "Hash Algorithm: %s\n", hash_str) <= 0 || !BIO_indent(bp, indent, 128) || // - BIO_puts(bp, "Mask Algorithm: ") <= 0) { - goto err; - } - - if (pss->maskGenAlgorithm) { - maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm); - if (maskHash == NULL) { - if (BIO_puts(bp, "INVALID") <= 0) { - goto err; - } - } else { - if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 || - BIO_puts(bp, " with ") <= 0 || - i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) { - goto err; - } - } - } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) { - goto err; - } - BIO_puts(bp, "\n"); - - if (!BIO_indent(bp, indent, 128) || // - BIO_puts(bp, "Salt Length: 0x") <= 0) { - goto err; - } - - if (pss->saltLength) { - if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) { - goto err; - } - } else if (BIO_puts(bp, "14 (default)") <= 0) { - goto err; - } - BIO_puts(bp, "\n"); - - if (!BIO_indent(bp, indent, 128) || // - BIO_puts(bp, "Trailer Field: 0x") <= 0) { - goto err; - } - - if (pss->trailerField) { - if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) { - goto err; - } - } else if (BIO_puts(bp, "BC (default)") <= 0) { - goto err; + BIO_printf(bp, "Mask Algorithm: mgf1 with %s\n", hash_str) <= 0 || + !BIO_indent(bp, indent, 128) || // + BIO_printf(bp, "Salt Length: 0x%x\n", salt_len) <= 0 || + !BIO_indent(bp, indent, 128) || // + BIO_puts(bp, "Trailer Field: 0xBC (default)\n") <= 0) { + return 0; } - BIO_puts(bp, "\n"); - rv = 1; - -err: - RSA_PSS_PARAMS_free(pss); - X509_ALGOR_free(maskHash); - return rv; + return 1; } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/t_req.cc b/Sources/CCryptoBoringSSL/crypto/x509/t_req.cc index a7c62e019..8a778ba69 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/t_req.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/t_req.cc @@ -79,7 +79,7 @@ int X509_REQ_print_ex(BIO *bio, X509_REQ *x, unsigned long nmflags, if (!(cflag & X509_FLAG_NO_PUBKEY)) { if (BIO_write(bio, " Subject Public Key Info:\n", 33) <= 0 || BIO_printf(bio, "%12sPublic Key Algorithm: ", "") <= 0 || - i2a_ASN1_OBJECT(bio, ri->pubkey->algor->algorithm) <= 0 || + i2a_ASN1_OBJECT(bio, ri->pubkey->algor.algorithm) <= 0 || BIO_puts(bio, "\n") <= 0) { goto err; } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/t_x509.cc b/Sources/CCryptoBoringSSL/crypto/x509/t_x509.cc index 6f8be6c22..97fb41435 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/t_x509.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/t_x509.cc @@ -60,7 +60,6 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, nmindent = 16; } - const X509_CINF *ci = x->cert_info; if (!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bp, "Certificate:\n", 13) <= 0) { return 0; @@ -108,7 +107,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, } if (!(cflag & X509_FLAG_NO_SIGNAME)) { - if (X509_signature_print(bp, ci->signature, NULL) <= 0) { + if (X509_signature_print(bp, &x->tbs_sig_alg, NULL) <= 0) { return 0; } } @@ -164,7 +163,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) { return 0; } - if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) { + if (i2a_ASN1_OBJECT(bp, x->key.algor.algorithm) <= 0) { return 0; } if (BIO_puts(bp, "\n") <= 0) { @@ -181,30 +180,30 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, } if (!(cflag & X509_FLAG_NO_IDS)) { - if (ci->issuerUID) { + if (x->issuerUID) { if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0) { return 0; } - if (!X509_signature_dump(bp, ci->issuerUID, 12)) { + if (!X509_signature_dump(bp, x->issuerUID, 12)) { return 0; } } - if (ci->subjectUID) { + if (x->subjectUID) { if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0) { return 0; } - if (!X509_signature_dump(bp, ci->subjectUID, 12)) { + if (!X509_signature_dump(bp, x->subjectUID, 12)) { return 0; } } } if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { - X509V3_extensions_print(bp, "X509v3 extensions", ci->extensions, cflag, 8); + X509V3_extensions_print(bp, "X509v3 extensions", x->extensions, cflag, 8); } if (!(cflag & X509_FLAG_NO_SIGDUMP)) { - if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0) { + if (X509_signature_print(bp, &x->sig_alg, &x->signature) <= 0) { return 0; } } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/v3_conf.cc b/Sources/CCryptoBoringSSL/crypto/x509/v3_conf.cc index 80588dad7..1e8c47703 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/v3_conf.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/v3_conf.cc @@ -308,7 +308,7 @@ int X509V3_EXT_add_nconf(const CONF *conf, const X509V3_CTX *ctx, const char *section, X509 *cert) { STACK_OF(X509_EXTENSION) **sk = NULL; if (cert) { - sk = &cert->cert_info->extensions; + sk = &cert->extensions; } return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/v3_purp.cc b/Sources/CCryptoBoringSSL/crypto/x509/v3_purp.cc index 4ab83a75e..fbe08767b 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/v3_purp.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/v3_purp.cc @@ -105,18 +105,18 @@ int X509_check_purpose(X509 *x, int id, int ca) { } const X509_PURPOSE *X509_PURPOSE_get0(int id) { - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(xstandard); i++) { - if (xstandard[i].purpose == id) { - return &xstandard[i]; + for (const auto &p : xstandard) { + if (p.purpose == id) { + return &p; } } return NULL; } int X509_PURPOSE_get_by_sname(const char *sname) { - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(xstandard); i++) { - if (strcmp(xstandard[i].sname, sname) == 0) { - return xstandard[i].purpose; + for (const auto &p : xstandard) { + if (strcmp(p.sname, sname) == 0) { + return p.purpose; } } return -1; diff --git a/Sources/CCryptoBoringSSL/crypto/x509/v3_skey.cc b/Sources/CCryptoBoringSSL/crypto/x509/v3_skey.cc index 3dd128908..704c0613f 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/v3_skey.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/v3_skey.cc @@ -65,7 +65,7 @@ static char *i2s_ASN1_OCTET_STRING_cb(const X509V3_EXT_METHOD *method, static void *s2i_skey_id(const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx, const char *str) { ASN1_OCTET_STRING *oct; - ASN1_BIT_STRING *pk; + const ASN1_BIT_STRING *pk; unsigned char pkey_dig[EVP_MAX_MD_SIZE]; unsigned int diglen; @@ -87,14 +87,9 @@ static void *s2i_skey_id(const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx, } if (ctx->subject_req) { - pk = ctx->subject_req->req_info->pubkey->public_key; + pk = &ctx->subject_req->req_info->pubkey->public_key; } else { - pk = ctx->subject_cert->cert_info->key->public_key; - } - - if (!pk) { - OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY); - goto err; + pk = &ctx->subject_cert->key.public_key; } if (!EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL)) { diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x509_cmp.cc b/Sources/CCryptoBoringSSL/crypto/x509/x509_cmp.cc index a857d0f7e..fcfdf81fa 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x509_cmp.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x509_cmp.cc @@ -29,15 +29,15 @@ int X509_issuer_name_cmp(const X509 *a, const X509 *b) { - return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer)); + return X509_NAME_cmp(a->issuer, b->issuer); } int X509_subject_name_cmp(const X509 *a, const X509 *b) { - return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject)); + return X509_NAME_cmp(a->subject, b->subject); } int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) { - return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer)); + return X509_NAME_cmp(a->crl->issuer, b->crl->issuer); } int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) { @@ -45,35 +45,31 @@ int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) { } X509_NAME *X509_get_issuer_name(const X509 *a) { - return a->cert_info->issuer; + // This function is not const-correct for OpenSSL compatibility. + return a->issuer; } -uint32_t X509_issuer_name_hash(X509 *x) { - return X509_NAME_hash(x->cert_info->issuer); -} +uint32_t X509_issuer_name_hash(X509 *x) { return X509_NAME_hash(x->issuer); } uint32_t X509_issuer_name_hash_old(X509 *x) { - return (X509_NAME_hash_old(x->cert_info->issuer)); + return X509_NAME_hash_old(x->issuer); } X509_NAME *X509_get_subject_name(const X509 *a) { - return a->cert_info->subject; + // This function is not const-correct for OpenSSL compatibility. + return a->subject; } -ASN1_INTEGER *X509_get_serialNumber(X509 *a) { - return a->cert_info->serialNumber; -} +ASN1_INTEGER *X509_get_serialNumber(X509 *a) { return &a->serialNumber; } const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x509) { - return x509->cert_info->serialNumber; + return &x509->serialNumber; } -uint32_t X509_subject_name_hash(X509 *x) { - return X509_NAME_hash(x->cert_info->subject); -} +uint32_t X509_subject_name_hash(X509 *x) { return X509_NAME_hash(x->subject); } uint32_t X509_subject_name_hash_old(X509 *x) { - return X509_NAME_hash_old(x->cert_info->subject); + return X509_NAME_hash_old(x->subject); } // Compare two certificates: they must be identical for this to work. NB: @@ -180,21 +176,22 @@ EVP_PKEY *X509_get0_pubkey(const X509 *x) { if (x == NULL) { return NULL; } - return X509_PUBKEY_get0(x->cert_info->key); + return X509_PUBKEY_get0(&x->key); } EVP_PKEY *X509_get_pubkey(const X509 *x) { if (x == NULL) { return NULL; } - return X509_PUBKEY_get(x->cert_info->key); + return X509_PUBKEY_get(&x->key); } ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) { if (!x) { return NULL; } - return x->cert_info->key->public_key; + // This function is not const-correct for OpenSSL compatibility. + return const_cast(&x->key.public_key); } int X509_check_private_key(const X509 *x, const EVP_PKEY *k) { diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x509_ext.cc b/Sources/CCryptoBoringSSL/crypto/x509/x509_ext.cc index 76f8591ce..8de88f08c 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x509_ext.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x509_ext.cc @@ -21,28 +21,38 @@ #include "internal.h" int X509_CRL_get_ext_count(const X509_CRL *x) { - return (X509v3_get_ext_count(x->crl->extensions)); + return X509v3_get_ext_count(x->crl->extensions); } int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos) { - return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos)); + return X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos); } int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, int lastpos) { - return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos)); + return X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos); } int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos) { - return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos)); + return X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos); } X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc) { - return (X509v3_get_ext(x->crl->extensions, loc)); + return X509v3_get_ext(x->crl->extensions, loc); +} + +static X509_EXTENSION *delete_ext(STACK_OF(X509_EXTENSION) **exts, int loc) { + X509_EXTENSION *ext = X509v3_delete_ext(*exts, loc); + // Empty extension lists are omitted. + if (*exts != nullptr && sk_X509_EXTENSION_num(*exts) == 0) { + sk_X509_EXTENSION_pop_free(*exts, X509_EXTENSION_free); + *exts = nullptr; + } + return ext; } X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc) { - return (X509v3_delete_ext(x->crl->extensions, loc)); + return delete_ext(&x->crl->extensions, loc); } void *X509_CRL_get_ext_d2i(const X509_CRL *crl, int nid, int *out_critical, @@ -56,76 +66,75 @@ int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, } int X509_CRL_add_ext(X509_CRL *x, const X509_EXTENSION *ex, int loc) { - return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL); + return X509v3_add_ext(&x->crl->extensions, ex, loc) != NULL; } int X509_get_ext_count(const X509 *x) { - return (X509v3_get_ext_count(x->cert_info->extensions)); + return X509v3_get_ext_count(x->extensions); } int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) { - return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos)); + return X509v3_get_ext_by_NID(x->extensions, nid, lastpos); } int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos) { - return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos)); + return X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos); } int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos) { - return (X509v3_get_ext_by_critical(x->cert_info->extensions, crit, lastpos)); + return X509v3_get_ext_by_critical(x->extensions, crit, lastpos); } X509_EXTENSION *X509_get_ext(const X509 *x, int loc) { - return (X509v3_get_ext(x->cert_info->extensions, loc)); + return X509v3_get_ext(x->extensions, loc); } X509_EXTENSION *X509_delete_ext(X509 *x, int loc) { - return (X509v3_delete_ext(x->cert_info->extensions, loc)); + return delete_ext(&x->extensions, loc); } int X509_add_ext(X509 *x, const X509_EXTENSION *ex, int loc) { - return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL); + return X509v3_add_ext(&x->extensions, ex, loc) != NULL; } void *X509_get_ext_d2i(const X509 *x509, int nid, int *out_critical, int *out_idx) { - return X509V3_get_d2i(x509->cert_info->extensions, nid, out_critical, - out_idx); + return X509V3_get_d2i(x509->extensions, nid, out_critical, out_idx); } int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags) { - return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit, flags); + return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); } int X509_REVOKED_get_ext_count(const X509_REVOKED *x) { - return (X509v3_get_ext_count(x->extensions)); + return X509v3_get_ext_count(x->extensions); } int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos) { - return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos)); + return X509v3_get_ext_by_NID(x->extensions, nid, lastpos); } int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, int lastpos) { - return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos)); + return X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos); } int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, int lastpos) { - return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos)); + return X509v3_get_ext_by_critical(x->extensions, crit, lastpos); } X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc) { - return (X509v3_get_ext(x->extensions, loc)); + return X509v3_get_ext(x->extensions, loc); } X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) { - return (X509v3_delete_ext(x->extensions, loc)); + return delete_ext(&x->extensions, loc); } int X509_REVOKED_add_ext(X509_REVOKED *x, const X509_EXTENSION *ex, int loc) { - return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); + return X509v3_add_ext(&x->extensions, ex, loc) != NULL; } void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *revoked, int nid, diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x509_lu.cc b/Sources/CCryptoBoringSSL/crypto/x509/x509_lu.cc index d8761324a..6a9173b1b 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x509_lu.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x509_lu.cc @@ -287,7 +287,6 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name, int *pnmatch) { X509_OBJECT stmp; X509 x509_s; - X509_CINF cinf_s; X509_CRL crl_s; X509_CRL_INFO crl_info_s; @@ -295,8 +294,7 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, switch (type) { case X509_LU_X509: stmp.data.x509 = &x509_s; - x509_s.cert_info = &cinf_s; - cinf_s.subject = name; + x509_s.subject = name; break; case X509_LU_CRL: stmp.data.crl = &crl_s; diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x509_set.cc b/Sources/CCryptoBoringSSL/crypto/x509/x509_set.cc index eb35621fd..22679acf0 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x509_set.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x509_set.cc @@ -21,13 +21,7 @@ #include "internal.h" -long X509_get_version(const X509 *x509) { - // The default version is v1(0). - if (x509->cert_info->version == NULL) { - return X509_VERSION_1; - } - return ASN1_INTEGER_get(x509->cert_info->version); -} +long X509_get_version(const X509 *x509) { return x509->version; } int X509_set_version(X509 *x, long version) { if (x == NULL) { @@ -39,20 +33,8 @@ int X509_set_version(X509 *x, long version) { return 0; } - // v1(0) is default and is represented by omitting the version. - if (version == X509_VERSION_1) { - ASN1_INTEGER_free(x->cert_info->version); - x->cert_info->version = NULL; - return 1; - } - - if (x->cert_info->version == NULL) { - x->cert_info->version = ASN1_INTEGER_new(); - if (x->cert_info->version == NULL) { - return 0; - } - } - return ASN1_INTEGER_set_int64(x->cert_info->version, version); + x->version = static_cast(version); + return 1; } int X509_set_serialNumber(X509 *x, const ASN1_INTEGER *serial) { @@ -61,138 +43,99 @@ int X509_set_serialNumber(X509 *x, const ASN1_INTEGER *serial) { return 0; } - ASN1_INTEGER *in; - if (x == NULL) { - return 0; - } - in = x->cert_info->serialNumber; - if (in != serial) { - in = ASN1_INTEGER_dup(serial); - if (in != NULL) { - ASN1_INTEGER_free(x->cert_info->serialNumber); - x->cert_info->serialNumber = in; - } - } - return in != NULL; + return ASN1_STRING_copy(&x->serialNumber, serial); } int X509_set_issuer_name(X509 *x, X509_NAME *name) { - if ((x == NULL) || (x->cert_info == NULL)) { + if (x == NULL) { return 0; } - return (X509_NAME_set(&x->cert_info->issuer, name)); + return (X509_NAME_set(&x->issuer, name)); } int X509_set_subject_name(X509 *x, X509_NAME *name) { - if ((x == NULL) || (x->cert_info == NULL)) { + if (x == NULL) { return 0; } - return (X509_NAME_set(&x->cert_info->subject, name)); + return (X509_NAME_set(&x->subject, name)); } int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) { - ASN1_TIME *in; - - if ((x == NULL) || (x->cert_info->validity == NULL)) { - return 0; - } - in = x->cert_info->validity->notBefore; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(x->cert_info->validity->notBefore); - x->cert_info->validity->notBefore = in; - } - } - return in != NULL; + // TODO(crbug.com/42290309): Check that |tm->type| is correct. + return ASN1_STRING_copy(&x->notBefore, tm); } int X509_set_notBefore(X509 *x, const ASN1_TIME *tm) { return X509_set1_notBefore(x, tm); } -const ASN1_TIME *X509_get0_notBefore(const X509 *x) { - return x->cert_info->validity->notBefore; -} +const ASN1_TIME *X509_get0_notBefore(const X509 *x) { return &x->notBefore; } ASN1_TIME *X509_getm_notBefore(X509 *x) { // Note this function takes a const |X509| pointer in OpenSSL. We require // non-const as this allows mutating |x|. If it comes up for compatibility, // we can relax this. - return x->cert_info->validity->notBefore; + return &x->notBefore; } ASN1_TIME *X509_get_notBefore(const X509 *x509) { // In OpenSSL, this function is an alias for |X509_getm_notBefore|, but our // |X509_getm_notBefore| is const-correct. |X509_get_notBefore| was // originally a macro, so it needs to capture both get0 and getm use cases. - return x509->cert_info->validity->notBefore; + return const_cast(&x509->notBefore); } int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) { - ASN1_TIME *in; - - if ((x == NULL) || (x->cert_info->validity == NULL)) { - return 0; - } - in = x->cert_info->validity->notAfter; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(x->cert_info->validity->notAfter); - x->cert_info->validity->notAfter = in; - } - } - return in != NULL; + // TODO(crbug.com/42290309): Check that |tm->type| is correct. + return ASN1_STRING_copy(&x->notAfter, tm); } int X509_set_notAfter(X509 *x, const ASN1_TIME *tm) { return X509_set1_notAfter(x, tm); } -const ASN1_TIME *X509_get0_notAfter(const X509 *x) { - return x->cert_info->validity->notAfter; -} +const ASN1_TIME *X509_get0_notAfter(const X509 *x) { return &x->notAfter; } ASN1_TIME *X509_getm_notAfter(X509 *x) { // Note this function takes a const |X509| pointer in OpenSSL. We require // non-const as this allows mutating |x|. If it comes up for compatibility, // we can relax this. - return x->cert_info->validity->notAfter; + return &x->notAfter; } ASN1_TIME *X509_get_notAfter(const X509 *x509) { // In OpenSSL, this function is an alias for |X509_getm_notAfter|, but our // |X509_getm_notAfter| is const-correct. |X509_get_notAfter| was // originally a macro, so it needs to capture both get0 and getm use cases. - return x509->cert_info->validity->notAfter; -} + return const_cast(&x509->notAfter); + } void X509_get0_uids(const X509 *x509, const ASN1_BIT_STRING **out_issuer_uid, const ASN1_BIT_STRING **out_subject_uid) { if (out_issuer_uid != NULL) { - *out_issuer_uid = x509->cert_info->issuerUID; + *out_issuer_uid = x509->issuerUID; } if (out_subject_uid != NULL) { - *out_subject_uid = x509->cert_info->subjectUID; + *out_subject_uid = x509->subjectUID; } } int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) { - if ((x == NULL) || (x->cert_info == NULL)) { + if (x == nullptr) { return 0; } - return (X509_PUBKEY_set(&(x->cert_info->key), pkey)); + return x509_pubkey_set1(&x->key, pkey); } const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x) { - return x->cert_info->extensions; + return x->extensions; } const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x) { - return x->cert_info->signature; + return &x->tbs_sig_alg; } X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x509) { - return x509->cert_info->key; + // This function is not const-correct for OpenSSL compatibility. + return const_cast(&x509->key); } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x509_trs.cc b/Sources/CCryptoBoringSSL/crypto/x509/x509_trs.cc index 0539d14db..3ac5b692d 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x509_trs.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x509_trs.cc @@ -43,9 +43,9 @@ static const X509_TRUST trstandard[] = { {X509_TRUST_TSA, trust_1oidany, NID_time_stamp}}; static const X509_TRUST *X509_TRUST_get0(int id) { - for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(trstandard); i++) { - if (trstandard[i].trust == id) { - return &trstandard[i]; + for (const auto &t : trstandard) { + if (t.trust == id) { + return &t; } } return NULL; diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x509cset.cc b/Sources/CCryptoBoringSSL/crypto/x509/x509cset.cc index 509705f18..7a3a5f1bb 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x509cset.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x509cset.cc @@ -209,19 +209,8 @@ int i2d_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp) { } int X509_CRL_set1_signature_algo(X509_CRL *crl, const X509_ALGOR *algo) { - X509_ALGOR *copy1 = X509_ALGOR_dup(algo); - X509_ALGOR *copy2 = X509_ALGOR_dup(algo); - if (copy1 == NULL || copy2 == NULL) { - X509_ALGOR_free(copy1); - X509_ALGOR_free(copy2); - return 0; - } - - X509_ALGOR_free(crl->sig_alg); - crl->sig_alg = copy1; - X509_ALGOR_free(crl->crl->sig_alg); - crl->crl->sig_alg = copy2; - return 1; + return X509_ALGOR_copy(crl->sig_alg, algo) && + X509_ALGOR_copy(crl->crl->sig_alg, algo); } int X509_CRL_set1_signature_value(X509_CRL *crl, const uint8_t *sig, diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x509rset.cc b/Sources/CCryptoBoringSSL/crypto/x509/x509rset.cc index 49837e740..616e5ada4 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x509rset.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x509rset.cc @@ -46,14 +46,7 @@ int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { } int X509_REQ_set1_signature_algo(X509_REQ *req, const X509_ALGOR *algo) { - X509_ALGOR *copy = X509_ALGOR_dup(algo); - if (copy == NULL) { - return 0; - } - - X509_ALGOR_free(req->sig_alg); - req->sig_alg = copy; - return 1; + return X509_ALGOR_copy(req->sig_alg, algo); } int X509_REQ_set1_signature_value(X509_REQ *req, const uint8_t *sig, diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x_algor.cc b/Sources/CCryptoBoringSSL/crypto/x509/x_algor.cc index f4d8ec38a..0d0623c1e 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x_algor.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x_algor.cc @@ -17,19 +17,131 @@ #include #include #include +#include #include +#include #include "../asn1/internal.h" +#include "../bytestring/internal.h" +#include "../internal.h" +#include "../mem_internal.h" #include "internal.h" -ASN1_SEQUENCE(X509_ALGOR) = { - ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT), - ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY), -} ASN1_SEQUENCE_END(X509_ALGOR) +void x509_algor_init(X509_ALGOR *alg) { + OPENSSL_memset(alg, 0, sizeof(X509_ALGOR)); + alg->algorithm = const_cast(OBJ_get_undef()); +} + +void x509_algor_cleanup(X509_ALGOR *alg) { + ASN1_OBJECT_free(alg->algorithm); + ASN1_TYPE_free(alg->parameter); +} + +X509_ALGOR *X509_ALGOR_new(void) { + bssl::UniquePtr ret = bssl::MakeUnique(); + if (ret == nullptr) { + return nullptr; + } + x509_algor_init(ret.get()); + return ret.release(); +} + +void X509_ALGOR_free(X509_ALGOR *alg) { + if (alg != nullptr) { + x509_algor_cleanup(alg); + OPENSSL_free(alg); + } +} + +int x509_parse_algorithm(CBS *cbs, X509_ALGOR *out) { + CBS seq; + if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } -IMPLEMENT_ASN1_FUNCTIONS_const(X509_ALGOR) -IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_ALGOR) + bssl::UniquePtr obj(asn1_parse_object(&seq, /*tag=*/0)); + if (obj == nullptr) { + return 0; + } + ASN1_OBJECT_free(out->algorithm); + out->algorithm = obj.release(); + if (CBS_len(&seq) == 0) { + ASN1_TYPE_free(out->parameter); + out->parameter = nullptr; + } else { + if (out->parameter == nullptr) { + out->parameter = ASN1_TYPE_new(); + } + if (out->parameter == nullptr || // + !asn1_parse_any(&seq, out->parameter)) { + return 0; + } + } + if (CBS_len(&seq) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + return 1; +} + +int x509_marshal_algorithm(CBB *out, const X509_ALGOR *in) { + CBB seq; + return CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) && + asn1_marshal_object(&seq, in->algorithm, /*tag=*/0) && + (in->parameter == nullptr || asn1_marshal_any(&seq, in->parameter)) && + CBB_flush(out); +} + +X509_ALGOR *d2i_X509_ALGOR(X509_ALGOR **out, const uint8_t **inp, long len) { + return bssl::D2IFromCBS( + out, inp, len, [](CBS *cbs) -> bssl::UniquePtr { + bssl::UniquePtr ret(X509_ALGOR_new()); + if (ret == nullptr || !x509_parse_algorithm(cbs, ret.get())) { + return nullptr; + } + return ret; + }); +} + +int i2d_X509_ALGOR(const X509_ALGOR *in, uint8_t **outp) { + return bssl::I2DFromCBB(/*initial_capacity=*/32, outp, [&](CBB *cbb) -> bool { + return x509_marshal_algorithm(cbb, in); + }); +} + +IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_ALGOR, X509_ALGOR_new, X509_ALGOR_free, + x509_parse_algorithm, i2d_X509_ALGOR) + +X509_ALGOR *X509_ALGOR_dup(const X509_ALGOR *alg) { + bssl::UniquePtr copy(X509_ALGOR_new()); + if (copy == nullptr || !X509_ALGOR_copy(copy.get(), alg)) { + return nullptr; + } + return copy.release(); +} + +int X509_ALGOR_copy(X509_ALGOR *dst, const X509_ALGOR *src) { + bssl::UniquePtr algorithm(OBJ_dup(src->algorithm)); + if (algorithm == nullptr) { + return 0; + } + bssl::UniquePtr parameter; + if (src->parameter != nullptr) { + parameter.reset(ASN1_TYPE_new()); + if (parameter == nullptr || + !ASN1_TYPE_set1(parameter.get(), src->parameter->type, + asn1_type_value_as_pointer(src->parameter))) { + return 0; + } + } + ASN1_OBJECT_free(dst->algorithm); + dst->algorithm = algorithm.release(); + ASN1_TYPE_free(dst->parameter); + dst->parameter = parameter.release(); + return 1; +} int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) { if (!alg) { @@ -106,11 +218,3 @@ int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) { } return ASN1_TYPE_cmp(a->parameter, b->parameter); } - -int x509_marshal_algorithm(CBB *out, const X509_ALGOR *in) { - uint8_t *ptr; - int len = i2d_X509_ALGOR(in, NULL); - return len > 0 && // - CBB_add_space(out, &ptr, static_cast(len)) && - i2d_X509_ALGOR(in, &ptr) == len; -} diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x_all.cc b/Sources/CCryptoBoringSSL/crypto/x509/x_all.cc index d4dd7a4a4..ee6f7ae9a 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x_all.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x_all.cc @@ -17,24 +17,33 @@ #include #include +#include #include #include #include #include #include +#include #include #include "../asn1/internal.h" +#include "../internal.h" #include "internal.h" int X509_verify(X509 *x509, EVP_PKEY *pkey) { - if (X509_ALGOR_cmp(x509->sig_alg, x509->cert_info->signature)) { + if (X509_ALGOR_cmp(&x509->sig_alg, &x509->tbs_sig_alg)) { OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH); return 0; } - return ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), x509->sig_alg, - x509->signature, x509->cert_info, pkey); + // This uses the cached TBSCertificate encoding, if any. + bssl::ScopedCBB cbb; + if (!CBB_init(cbb.get(), 128) || !x509_marshal_tbs_cert(cbb.get(), x509)) { + return 0; + } + return x509_verify_signature( + &x509->sig_alg, &x509->signature, + bssl::Span(CBB_data(cbb.get()), CBB_len(cbb.get())), pkey); } int X509_REQ_verify(X509_REQ *req, EVP_PKEY *pkey) { @@ -43,21 +52,41 @@ int X509_REQ_verify(X509_REQ *req, EVP_PKEY *pkey) { } int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) { - asn1_encoding_clear(&x->cert_info->enc); - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, - x->sig_alg, x->signature, x->cert_info, pkey, md)); + bssl::ScopedEVP_MD_CTX ctx; + if (!EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, pkey)) { + return 0; + } + return X509_sign_ctx(x, ctx.get()); } int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) { - asn1_encoding_clear(&x->cert_info->enc); - return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, - x->sig_alg, x->signature, x->cert_info, ctx); + // Historically, this function called |EVP_MD_CTX_cleanup| on return. Some + // callers rely on this to avoid memory leaks. + bssl::Cleanup cleanup = [&] { EVP_MD_CTX_cleanup(ctx); }; + + // Fill in the two copies of AlgorithmIdentifier. Note one of these modifies + // the TBSCertificate. + if (!x509_digest_sign_algorithm(ctx, &x->tbs_sig_alg) || + !x509_digest_sign_algorithm(ctx, &x->sig_alg)) { + return 0; + } + + // Discard the cached encoding. (We just modified it.) + CRYPTO_BUFFER_free(x->buf); + x->buf = nullptr; + + bssl::ScopedCBB cbb; + if (!CBB_init(cbb.get(), 128) || !x509_marshal_tbs_cert(cbb.get(), x)) { + return 0; + } + return x509_sign_to_bit_string( + ctx, &x->signature, bssl::Span(CBB_data(cbb.get()), CBB_len(cbb.get()))); } int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { asn1_encoding_clear(&x->req_info->enc); - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, - x->signature, x->req_info, pkey, md)); + return ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, + x->signature, x->req_info, pkey, md); } int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) { @@ -68,8 +97,8 @@ int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) { int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) { asn1_encoding_clear(&x->crl->enc); - return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg, - x->sig_alg, x->signature, x->crl, pkey, md)); + return ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg, + x->sig_alg, x->signature, x->crl, pkey, md); } int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) { @@ -79,13 +108,13 @@ int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) { } int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) { - return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL, - x->signature, x->spkac, pkey, md)); + return ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL, + x->signature, x->spkac, pkey, md); } int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *spki, EVP_PKEY *pkey) { - return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), spki->sig_algor, - spki->signature, spki->spkac, pkey)); + return ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), spki->sig_algor, + spki->signature, spki->spkac, pkey); } X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) { diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x_name.cc b/Sources/CCryptoBoringSSL/crypto/x509/x_name.cc index a5fae0458..5f6da5ae7 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x_name.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x_name.cc @@ -38,15 +38,6 @@ DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY) #define X509_NAME_MAX (1024 * 1024) -static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, - long len, const ASN1_ITEM *it, int opt, - ASN1_TLC *ctx); - -static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, - const ASN1_ITEM *it); -static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); -static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); - static int x509_name_encode(X509_NAME *a); static int x509_name_canon(X509_NAME *a); static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in); @@ -77,19 +68,8 @@ ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) // representing the ASN1. Unfortunately X509_NAME uses a completely different // form and caches encodings so we have to process the internal form and // convert to the external form. - -static const ASN1_EXTERN_FUNCS x509_name_ff = { - x509_name_ex_new, - x509_name_ex_free, - x509_name_ex_d2i, - x509_name_ex_i2d, -}; - -IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) - -IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) - -IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) +// +// TODO(crbug.com/42290417): Rewrite all this with |CBS| and |CBB|. static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) { X509_NAME *ret = NULL; @@ -143,29 +123,37 @@ static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) { sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); } -static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, - long len, const ASN1_ITEM *it, int opt, - ASN1_TLC *ctx) { - const unsigned char *p = *in, *q; +static int x509_name_ex_parse(ASN1_VALUE **val, CBS *cbs, const ASN1_ITEM *it, + int opt) { + if (opt && !CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) { + return 1; + } + + CBS elem; + if (!CBS_get_asn1_element(cbs, &elem, CBS_ASN1_SEQUENCE) || + // Bound the size of an X509_NAME we are willing to parse. + CBS_len(&elem) > X509_NAME_MAX) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + + // TODO(crbug.com/42290417): Rewrite the parser and canonicalization code with + // CBS and CBB. For now this calls into the original two-layer d2i code. + long len = static_cast(CBS_len(&elem)); + const unsigned char *p = CBS_data(&elem), *q; STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; X509_NAME *nm = NULL; size_t i, j; - int ret; STACK_OF(X509_NAME_ENTRY) *entries; X509_NAME_ENTRY *entry; - // Bound the size of an X509_NAME we are willing to parse. - if (len > X509_NAME_MAX) { - len = X509_NAME_MAX; - } q = p; // Get internal representation of Name ASN1_VALUE *intname_val = NULL; - ret = ASN1_item_ex_d2i(&intname_val, &p, len, - ASN1_ITEM_rptr(X509_NAME_INTERNAL), /*tag=*/-1, - /*aclass=*/0, opt, /*buf=*/NULL); - if (ret <= 0) { - return ret; + if (ASN1_item_ex_d2i(&intname_val, &p, len, + ASN1_ITEM_rptr(X509_NAME_INTERNAL), /*tag=*/-1, + /*aclass=*/0, /*opt=*/0) <= 0) { + return 0; } intname = (STACK_OF(STACK_OF_X509_NAME_ENTRY) *)intname_val; @@ -195,15 +183,13 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, (void)sk_X509_NAME_ENTRY_set(entries, j, NULL); } } - ret = x509_name_canon(nm); - if (!ret) { + if (!x509_name_canon(nm)) { goto err; } sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, local_sk_X509_NAME_ENTRY_free); nm->modified = 0; *val = (ASN1_VALUE *)nm; - *in = p; - return ret; + return 1; err: X509_NAME_free(nm); sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, @@ -226,6 +212,12 @@ static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, return ret; } +static const ASN1_EXTERN_FUNCS x509_name_ff = { + x509_name_ex_new, x509_name_ex_free, x509_name_ex_parse, x509_name_ex_i2d}; +IMPLEMENT_EXTERN_ASN1(X509_NAME, x509_name_ff) +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) + static int x509_name_encode(X509_NAME *a) { int len; unsigned char *p; diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x_pubkey.cc b/Sources/CCryptoBoringSSL/crypto/x509/x_pubkey.cc index 07dc78157..ca19d9a32 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x_pubkey.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x_pubkey.cc @@ -23,94 +23,139 @@ #include #include #include +#include +#include "../asn1/internal.h" +#include "../bytestring/internal.h" +#include "../evp/internal.h" #include "../internal.h" +#include "../mem_internal.h" #include "internal.h" -static void x509_pubkey_changed(X509_PUBKEY *pub) { - EVP_PKEY_free(pub->pkey); - pub->pkey = NULL; - - // Re-encode the |X509_PUBKEY| to DER and parse it with EVP's APIs. - uint8_t *spki = NULL; - int spki_len = i2d_X509_PUBKEY(pub, &spki); - EVP_PKEY *pkey; - if (spki_len < 0) { - goto err; +void x509_pubkey_init(X509_PUBKEY *key) { + OPENSSL_memset(key, 0, sizeof(X509_PUBKEY)); + x509_algor_init(&key->algor); + asn1_string_init(&key->public_key, V_ASN1_BIT_STRING); +} + +X509_PUBKEY *X509_PUBKEY_new(void) { + bssl::UniquePtr ret = bssl::MakeUnique(); + if (ret == nullptr) { + return nullptr; } + x509_pubkey_init(ret.get()); + return ret.release(); +} - CBS cbs; - CBS_init(&cbs, spki, (size_t)spki_len); - pkey = EVP_parse_public_key(&cbs); - if (pkey == NULL || CBS_len(&cbs) != 0) { - EVP_PKEY_free(pkey); - goto err; +void x509_pubkey_cleanup(X509_PUBKEY *key) { + x509_algor_cleanup(&key->algor); + asn1_string_cleanup(&key->public_key); + EVP_PKEY_free(key->pkey); +} + +void X509_PUBKEY_free(X509_PUBKEY *key) { + if (key != nullptr) { + x509_pubkey_cleanup(key); + OPENSSL_free(key); } +} - pub->pkey = pkey; +static void x509_pubkey_changed(X509_PUBKEY *pub, + bssl::Span algs) { + EVP_PKEY_free(pub->pkey); + pub->pkey = nullptr; + + // Re-encode the |X509_PUBKEY| to DER and parse it with EVP's APIs. If the + // operation fails, clear errors. An |X509_PUBKEY| whose key we cannot parse + // is still a valid SPKI. It just cannot be converted to an |EVP_PKEY|. + bssl::ScopedCBB cbb; + if (!CBB_init(cbb.get(), 64) || !x509_marshal_public_key(cbb.get(), pub)) { + ERR_clear_error(); + return; + } + bssl::UniquePtr pkey(EVP_PKEY_from_subject_public_key_info( + CBB_data(cbb.get()), CBB_len(cbb.get()), algs.data(), algs.size())); + if (pkey == nullptr) { + ERR_clear_error(); + return; + } -err: - OPENSSL_free(spki); - // If the operation failed, clear errors. An |X509_PUBKEY| whose key we cannot - // parse is still a valid SPKI. It just cannot be converted to an |EVP_PKEY|. - ERR_clear_error(); + pub->pkey = pkey.release(); } -static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, - void *exarg) { - X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; - if (operation == ASN1_OP_FREE_POST) { - EVP_PKEY_free(pubkey->pkey); - } else if (operation == ASN1_OP_D2I_POST) { - x509_pubkey_changed(pubkey); +int x509_parse_public_key(CBS *cbs, X509_PUBKEY *out, + bssl::Span algs) { + CBS seq; + if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE) || + !x509_parse_algorithm(&seq, &out->algor) || + !asn1_parse_bit_string(&seq, &out->public_key, /*tag=*/0) || + CBS_len(&seq) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; } + x509_pubkey_changed(out, algs); return 1; } -ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { - ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), - ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING), -} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) +static int x509_parse_public_key_default(CBS *cbs, X509_PUBKEY *out) { + return x509_parse_public_key(cbs, out, bssl::GetDefaultEVPAlgorithms()); +} -IMPLEMENT_ASN1_FUNCTIONS_const(X509_PUBKEY) +int x509_marshal_public_key(CBB *cbb, const X509_PUBKEY *in) { + CBB seq; + return CBB_add_asn1(cbb, &seq, CBS_ASN1_SEQUENCE) && + x509_marshal_algorithm(&seq, &in->algor) && + asn1_marshal_bit_string(&seq, &in->public_key, /*tag=*/0) && + CBB_flush(cbb); +} -int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) { - X509_PUBKEY *pk = NULL; - uint8_t *spki = NULL; - size_t spki_len; +X509_PUBKEY *d2i_X509_PUBKEY(X509_PUBKEY **out, const uint8_t **inp, long len) { + return bssl::D2IFromCBS( + out, inp, len, [](CBS *cbs) -> bssl::UniquePtr { + bssl::UniquePtr ret(X509_PUBKEY_new()); + if (ret == nullptr || !x509_parse_public_key_default(cbs, ret.get())) { + return nullptr; + } + return ret; + }); +} - if (x == NULL) { - return 0; - } +int i2d_X509_PUBKEY(const X509_PUBKEY *key, uint8_t **outp) { + return bssl::I2DFromCBB(/*initial_capacity=*/32, outp, [&](CBB *cbb) -> bool { + return x509_marshal_public_key(cbb, key); + }); +} - CBB cbb; - const uint8_t *p; - if (!CBB_init(&cbb, 0) || // - !EVP_marshal_public_key(&cbb, pkey) || - !CBB_finish(&cbb, &spki, &spki_len) || // - spki_len > LONG_MAX) { - CBB_cleanup(&cbb); +// TODO(crbug.com/42290417): Remove this when |X509| and |X509_REQ| no longer +// depend on the tables. +IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_PUBKEY, X509_PUBKEY_new, X509_PUBKEY_free, + x509_parse_public_key_default, i2d_X509_PUBKEY) + +int x509_pubkey_set1(X509_PUBKEY *key, EVP_PKEY *pkey) { + bssl::ScopedCBB cbb; + if (!CBB_init(cbb.get(), 64) || + !EVP_marshal_public_key(cbb.get(), pkey)) { OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR); - goto error; + return 0; } - p = spki; - pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len); - if (pk == NULL || p != spki + spki_len) { - OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR); - goto error; - } + CBS cbs; + CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get())); + // TODO(crbug.com/42290364): Use an |EVP_PKEY_ALG| derived from |pkey|. + // |X509_PUBKEY_get0| does not currently work when setting, say, an + // |EVP_PKEY_RSA_PSS| key. + return x509_parse_public_key(&cbs, key, bssl::GetDefaultEVPAlgorithms()); +} - OPENSSL_free(spki); +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) { + bssl::UniquePtr new_key(X509_PUBKEY_new()); + if (new_key == nullptr || !x509_pubkey_set1(new_key.get(), pkey)) { + return 0; + } X509_PUBKEY_free(*x); - *x = pk; - + *x = new_key.release(); return 1; -error: - X509_PUBKEY_free(pk); - OPENSSL_free(spki); - return 0; } EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key) { @@ -136,16 +181,16 @@ EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key) { int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, int param_type, void *param_value, uint8_t *key, int key_len) { - if (!X509_ALGOR_set0(pub->algor, obj, param_type, param_value)) { + if (!X509_ALGOR_set0(&pub->algor, obj, param_type, param_value)) { return 0; } - ASN1_STRING_set0(pub->public_key, key, key_len); + ASN1_STRING_set0(&pub->public_key, key, key_len); // Set the number of unused bits to zero. - pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + pub->public_key.flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pub->public_key.flags |= ASN1_STRING_FLAG_BITS_LEFT; - x509_pubkey_changed(pub); + x509_pubkey_changed(pub, bssl::GetDefaultEVPAlgorithms()); return 1; } @@ -153,18 +198,18 @@ int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, const uint8_t **out_key, int *out_key_len, X509_ALGOR **out_alg, X509_PUBKEY *pub) { if (out_obj != NULL) { - *out_obj = pub->algor->algorithm; + *out_obj = pub->algor.algorithm; } if (out_key != NULL) { - *out_key = pub->public_key->data; - *out_key_len = pub->public_key->length; + *out_key = pub->public_key.data; + *out_key_len = pub->public_key.length; } if (out_alg != NULL) { - *out_alg = pub->algor; + *out_alg = &pub->algor; } return 1; } const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key(const X509_PUBKEY *pub) { - return pub->public_key; + return &pub->public_key; } diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x_val.cc b/Sources/CCryptoBoringSSL/crypto/x509/x_val.cc deleted file mode 100644 index 188df6977..000000000 --- a/Sources/CCryptoBoringSSL/crypto/x509/x_val.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include - -#include -#include - -#include "internal.h" - - -ASN1_SEQUENCE(X509_VAL) = { - ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME), - ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME), -} ASN1_SEQUENCE_END(X509_VAL) - -IMPLEMENT_ASN1_FUNCTIONS_const(X509_VAL) diff --git a/Sources/CCryptoBoringSSL/crypto/x509/x_x509.cc b/Sources/CCryptoBoringSSL/crypto/x509/x_x509.cc index ec1037cc4..0e570801c 100644 --- a/Sources/CCryptoBoringSSL/crypto/x509/x_x509.cc +++ b/Sources/CCryptoBoringSSL/crypto/x509/x_x509.cc @@ -27,57 +27,57 @@ #include "../asn1/internal.h" #include "../bytestring/internal.h" +#include "../evp/internal.h" #include "../internal.h" #include "internal.h" static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; -ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = { - ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), - ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER), - ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR), - ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), - ASN1_SIMPLE(X509_CINF, validity, X509_VAL), - ASN1_SIMPLE(X509_CINF, subject, X509_NAME), - ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), - ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), - ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), - ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3), -} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF) - -IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) - -// x509_new_null returns a new |X509| object where the |cert_info|, |sig_alg|, -// and |signature| fields are not yet filled in. -static X509 *x509_new_null(void) { - X509 *ret = reinterpret_cast(OPENSSL_zalloc(sizeof(X509))); - if (ret == NULL) { - return NULL; +static constexpr CBS_ASN1_TAG kVersionTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0; +static constexpr CBS_ASN1_TAG kIssuerUIDTag = CBS_ASN1_CONTEXT_SPECIFIC | 1; +static constexpr CBS_ASN1_TAG kSubjectUIDTag = CBS_ASN1_CONTEXT_SPECIFIC | 2; +static constexpr CBS_ASN1_TAG kExtensionsTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3; + +// x509_new_null returns a new |X509| object where the |issuer| and |subject| +// fields are not yet filled in. +static bssl::UniquePtr x509_new_null(void) { + bssl::UniquePtr ret( + reinterpret_cast(OPENSSL_zalloc(sizeof(X509)))); + if (ret == nullptr) { + return nullptr; } ret->references = 1; ret->ex_pathlen = -1; + ret->version = X509_VERSION_1; + asn1_string_init(&ret->serialNumber, V_ASN1_INTEGER); + x509_algor_init(&ret->tbs_sig_alg); + asn1_string_init(&ret->notBefore, -1); + asn1_string_init(&ret->notAfter, -1); + x509_pubkey_init(&ret->key); + x509_algor_init(&ret->sig_alg); + asn1_string_init(&ret->signature, V_ASN1_BIT_STRING); CRYPTO_new_ex_data(&ret->ex_data); CRYPTO_MUTEX_init(&ret->lock); return ret; } X509 *X509_new(void) { - X509 *ret = x509_new_null(); - if (ret == NULL) { - return NULL; + bssl::UniquePtr ret = x509_new_null(); + if (ret == nullptr) { + return nullptr; } - - ret->cert_info = X509_CINF_new(); - ret->sig_alg = X509_ALGOR_new(); - ret->signature = ASN1_BIT_STRING_new(); - if (ret->cert_info == NULL || ret->sig_alg == NULL || - ret->signature == NULL) { - X509_free(ret); - return NULL; + // TODO(crbug.com/42290417): When the |X509_NAME| parser is CBS-based and + // writes into a pre-existing |X509_NAME|, we will no longer need the + // |X509_new| and |x509_new_null| split. + ret->issuer = X509_NAME_new(); + ret->subject = X509_NAME_new(); + if (ret->issuer == nullptr || ret->subject == nullptr) { + return nullptr; } - - return ret; + return ret.release(); } void X509_free(X509 *x509) { @@ -87,9 +87,19 @@ void X509_free(X509 *x509) { CRYPTO_free_ex_data(&g_ex_data_class, &x509->ex_data); - X509_CINF_free(x509->cert_info); - X509_ALGOR_free(x509->sig_alg); - ASN1_BIT_STRING_free(x509->signature); + asn1_string_cleanup(&x509->serialNumber); + x509_algor_cleanup(&x509->tbs_sig_alg); + X509_NAME_free(x509->issuer); + asn1_string_cleanup(&x509->notBefore); + asn1_string_cleanup(&x509->notAfter); + X509_NAME_free(x509->subject); + x509_pubkey_cleanup(&x509->key); + ASN1_BIT_STRING_free(x509->issuerUID); + ASN1_BIT_STRING_free(x509->subjectUID); + sk_X509_EXTENSION_pop_free(x509->extensions, X509_EXTENSION_free); + x509_algor_cleanup(&x509->sig_alg); + asn1_string_cleanup(&x509->signature); + CRYPTO_BUFFER_free(x509->buf); ASN1_OCTET_STRING_free(x509->skid); AUTHORITY_KEYID_free(x509->akid); CRL_DIST_POINTS_free(x509->crldp); @@ -101,115 +111,216 @@ void X509_free(X509 *x509) { OPENSSL_free(x509); } -static X509 *x509_parse(CBS *cbs, CRYPTO_BUFFER *buf) { - CBS cert, tbs, sigalg, sig; - if (!CBS_get_asn1(cbs, &cert, CBS_ASN1_SEQUENCE) || - // Bound the length to comfortably fit in an int. Lengths in this - // module often omit overflow checks. - CBS_len(&cert) > INT_MAX / 2 || - !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE) || - !CBS_get_asn1_element(&cert, &sigalg, CBS_ASN1_SEQUENCE)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); - return nullptr; - } - - // For just the signature field, we accept non-minimal BER lengths, though not - // indefinite-length encoding. See b/18228011. - // - // TODO(crbug.com/boringssl/354): Switch the affected callers to convert the - // certificate before parsing and then remove this workaround. - CBS_ASN1_TAG tag; - size_t header_len; - int indefinite; - if (!CBS_get_any_ber_asn1_element(&cert, &sig, &tag, &header_len, - /*out_ber_found=*/nullptr, - &indefinite) || - tag != CBS_ASN1_BITSTRING || indefinite || // - !CBS_skip(&sig, header_len) || // - CBS_len(&cert) != 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); - return nullptr; +static int parse_name(CBS *cbs, X509_NAME **out) { + // TODO(crbug.com/42290417): Make the |X509_NAME| parser CBS-based and avoid + // this awkward conversion. + const uint8_t *p = CBS_data(cbs); + X509_NAME_free(*out); + *out = d2i_X509_NAME(nullptr, &p, CBS_len(cbs)); + if (*out == nullptr) { + return 0; } + BSSL_CHECK(CBS_skip(cbs, p - CBS_data(cbs))); + return 1; +} +X509 *X509_parse_with_algorithms(CRYPTO_BUFFER *buf, + const EVP_PKEY_ALG *const *algs, + size_t num_algs) { bssl::UniquePtr ret(x509_new_null()); if (ret == nullptr) { return nullptr; } - // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled - // from the tasn_*.c implementation, replace this with |CBS|-based - // functions. - const uint8_t *inp = CBS_data(&tbs); - if (ASN1_item_ex_d2i((ASN1_VALUE **)&ret->cert_info, &inp, CBS_len(&tbs), - ASN1_ITEM_rptr(X509_CINF), /*tag=*/-1, - /*aclass=*/0, /*opt=*/0, buf) <= 0 || - inp != CBS_data(&tbs) + CBS_len(&tbs)) { - return nullptr; - } + // Save the buffer to cache the original encoding. + ret->buf = bssl::UpRef(buf).release(); - inp = CBS_data(&sigalg); - ret->sig_alg = d2i_X509_ALGOR(nullptr, &inp, CBS_len(&sigalg)); - if (ret->sig_alg == nullptr || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) { + // Parse the Certificate. + CBS cbs, cert, tbs; + CRYPTO_BUFFER_init_CBS(buf, &cbs); + if (!CBS_get_asn1(&cbs, &cert, CBS_ASN1_SEQUENCE) || // + CBS_len(&cbs) != 0 || + // Bound the length to comfortably fit in an int. Lengths in this + // module often omit overflow checks. + CBS_len(&cert) > INT_MAX / 2 || + !CBS_get_asn1(&cert, &tbs, CBS_ASN1_SEQUENCE) || + !x509_parse_algorithm(&cert, &ret->sig_alg) || + // For just the signature field, we accept non-minimal BER lengths, though + // not indefinite-length encoding. See b/18228011. + // + // TODO(crbug.com/boringssl/354): Switch the affected callers to convert + // the certificate before parsing and then remove this workaround. + !asn1_parse_bit_string_with_bad_length(&cert, &ret->signature) || + CBS_len(&cert) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); return nullptr; } - inp = CBS_data(&sig); - ret->signature = c2i_ASN1_BIT_STRING(nullptr, &inp, CBS_len(&sig)); - if (ret->signature == nullptr || inp != CBS_data(&sig) + CBS_len(&sig)) { + // Parse the TBSCertificate. + if (CBS_peek_asn1_tag(&tbs, kVersionTag)) { + CBS wrapper; + uint64_t version; + if (!CBS_get_asn1(&tbs, &wrapper, kVersionTag) || + !CBS_get_asn1_uint64(&wrapper, &version) || // + CBS_len(&wrapper) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return nullptr; + } + // The version must be one of v1(0), v2(1), or v3(2). + // TODO(https://crbug.com/42290225): Also reject |X509_VERSION_1|. v1 is + // DEFAULT, so DER requires it be omitted. + if (version != X509_VERSION_1 && version != X509_VERSION_2 && + version != X509_VERSION_3) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + return nullptr; + } + ret->version = static_cast(version); + } else { + ret->version = X509_VERSION_1; + } + CBS validity; + if (!asn1_parse_integer(&tbs, &ret->serialNumber, /*tag=*/0) || + !x509_parse_algorithm(&tbs, &ret->tbs_sig_alg) || + !parse_name(&tbs, &ret->issuer) || + !CBS_get_asn1(&tbs, &validity, CBS_ASN1_SEQUENCE) || + !asn1_parse_time(&validity, &ret->notBefore, + /*allow_utc_timezone_offset=*/1) || + !asn1_parse_time(&validity, &ret->notAfter, + /*allow_utc_timezone_offset=*/1) || + CBS_len(&validity) != 0 || // + !parse_name(&tbs, &ret->subject) || + !x509_parse_public_key(&tbs, &ret->key, bssl::Span(algs, num_algs))) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); return nullptr; } - - // The version must be one of v1(0), v2(1), or v3(2). - long version = X509_VERSION_1; - if (ret->cert_info->version != nullptr) { - version = ASN1_INTEGER_get(ret->cert_info->version); - // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should - // also be rejected here. This means an explicitly-encoded X.509v1 - // version. v1 is DEFAULT, so DER requires it be omitted. - if (version < X509_VERSION_1 || version > X509_VERSION_3) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); + // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3: + if (ret->version >= X509_VERSION_2 && + CBS_peek_asn1_tag(&tbs, kIssuerUIDTag)) { + ret->issuerUID = ASN1_BIT_STRING_new(); + if (ret->issuerUID == nullptr || + !asn1_parse_bit_string(&tbs, ret->issuerUID, kIssuerUIDTag)) { return nullptr; } } - - // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3. - if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != nullptr || - ret->cert_info->subjectUID != nullptr)) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); - return nullptr; + if (ret->version >= X509_VERSION_2 && + CBS_peek_asn1_tag(&tbs, kSubjectUIDTag)) { + ret->subjectUID = ASN1_BIT_STRING_new(); + if (ret->subjectUID == nullptr || + !asn1_parse_bit_string(&tbs, ret->subjectUID, kSubjectUIDTag)) { + return nullptr; + } } - - // Per RFC 5280, section 4.1.2.9, extensions require v3. - if (version != X509_VERSION_3 && ret->cert_info->extensions != nullptr) { - OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION); + // Per RFC 5280, section 4.1.2.9, extensions require v3: + if (ret->version >= X509_VERSION_3 && + CBS_peek_asn1_tag(&tbs, kExtensionsTag)) { + CBS wrapper; + if (!CBS_get_asn1(&tbs, &wrapper, kExtensionsTag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return nullptr; + } + // TODO(crbug.com/42290219): Empty extension lists should be rejected. An + // empty extensions list is encoded by omitting the field altogether. libpki + // already rejects this. + const uint8_t *p = CBS_data(&wrapper); + ret->extensions = d2i_X509_EXTENSIONS(nullptr, &p, CBS_len(&wrapper)); + if (ret->extensions == nullptr || + p != CBS_data(&wrapper) + CBS_len(&wrapper)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return nullptr; + } + } + if (CBS_len(&tbs) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); return nullptr; } return ret.release(); } -X509 *d2i_X509(X509 **out, const uint8_t **inp, long len) { - X509 *ret = NULL; - if (len < 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); - goto err; +X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) { + auto algs = bssl::GetDefaultEVPAlgorithms(); + return X509_parse_with_algorithms(buf, algs.data(), algs.size()); +} + +static bssl::UniquePtr x509_parse(CBS *cbs) { + CBS cert; + if (!CBS_get_asn1_element(cbs, &cert, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return nullptr; } - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - ret = x509_parse(&cbs, NULL); - if (ret == NULL) { - goto err; + bssl::UniquePtr buf(CRYPTO_BUFFER_new_from_CBS(&cert, nullptr)); + if (buf == nullptr) { + return nullptr; } + return bssl::UniquePtr(X509_parse_from_buffer(buf.get())); +} - *inp = CBS_data(&cbs); +int x509_marshal_tbs_cert(CBB *cbb, X509 *x509) { + if (x509->buf != nullptr) { + // Replay the saved TBSCertificate from the |CRYPTO_BUFFER|, to verify + // exactly what we parsed. The |CRYPTO_BUFFER| contains the full + // Certificate, so we need to find the TBSCertificate portion. + CBS cbs, cert, tbs; + CRYPTO_BUFFER_init_CBS(x509->buf, &cbs); + if (!CBS_get_asn1(&cbs, &cert, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE)) { + // This should be impossible. + OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); + return 0; + } + return CBB_add_bytes(cbb, CBS_data(&tbs), CBS_len(&tbs)); + } -err: - if (out != NULL) { - X509_free(*out); - *out = ret; + // No saved TBSCertificate encoding. Encode it anew. + CBB tbs, version, validity, extensions; + if (!CBB_add_asn1(cbb, &tbs, CBS_ASN1_SEQUENCE)) { + return 0; } - return ret; + if (x509->version != X509_VERSION_1) { + if (!CBB_add_asn1(&tbs, &version, kVersionTag) || + !CBB_add_asn1_uint64(&version, x509->version)) { + return 0; + } + } + if (!asn1_marshal_integer(&tbs, &x509->serialNumber, /*tag=*/0) || + !x509_marshal_algorithm(&tbs, &x509->tbs_sig_alg) || + !x509_marshal_name(&tbs, x509->issuer) || + !CBB_add_asn1(&tbs, &validity, CBS_ASN1_SEQUENCE) || + !asn1_marshal_time(&validity, &x509->notBefore) || + !asn1_marshal_time(&validity, &x509->notAfter) || + !x509_marshal_name(&tbs, x509->subject) || + !x509_marshal_public_key(&tbs, &x509->key) || + (x509->issuerUID != nullptr && + !asn1_marshal_bit_string(&tbs, x509->issuerUID, kIssuerUIDTag)) || + (x509->subjectUID != nullptr && + !asn1_marshal_bit_string(&tbs, x509->subjectUID, kSubjectUIDTag))) { + return 0; + } + if (x509->extensions != nullptr) { + int len = i2d_X509_EXTENSIONS(x509->extensions, nullptr); + uint8_t *out; + if (len <= 0 || // + !CBB_add_asn1(&tbs, &extensions, kExtensionsTag) || + !CBB_add_space(&extensions, &out, len) || + i2d_X509_EXTENSIONS(x509->extensions, &out) != len) { + return 0; + } + } + return CBB_flush(cbb); +} + +static int x509_marshal(CBB *cbb, X509 *x509) { + CBB cert; + return CBB_add_asn1(cbb, &cert, CBS_ASN1_SEQUENCE) && + x509_marshal_tbs_cert(&cert, x509) && + x509_marshal_algorithm(&cert, &x509->sig_alg) && + asn1_marshal_bit_string(&cert, &x509->signature, /*tag=*/0) && + CBB_flush(cbb); +} + +X509 *d2i_X509(X509 **out, const uint8_t **inp, long len) { + return bssl::D2IFromCBS(out, inp, len, x509_parse); } int i2d_X509(X509 *x509, uint8_t **outp) { @@ -218,26 +329,9 @@ int i2d_X509(X509 *x509, uint8_t **outp) { return -1; } - bssl::ScopedCBB cbb; - CBB cert; - if (!CBB_init(cbb.get(), 64) || // - !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE)) { - return -1; - } - - // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled - // from the tasn_*.c implementation, replace this with |CBS|-based functions. - uint8_t *out; - int len = i2d_X509_CINF(x509->cert_info, NULL); - if (len < 0 || // - !CBB_add_space(&cert, &out, static_cast(len)) || - i2d_X509_CINF(x509->cert_info, &out) != len || - !x509_marshal_algorithm(&cert, x509->sig_alg) || - !asn1_marshal_bit_string(&cert, x509->signature, /*tag=*/0)) { - return -1; - } - - return CBB_finish_i2d(cbb.get(), outp); + return bssl::I2DFromCBB( + /*initial_capacity=*/256, outp, + [&](CBB *cbb) -> bool { return x509_marshal(cbb, x509); }); } static int x509_new_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { @@ -250,27 +344,19 @@ static void x509_free_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { *pval = NULL; } -static int x509_d2i_cb(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, int opt, ASN1_TLC *ctx) { - if (len < 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL); - return 0; - } - - CBS cbs; - CBS_init(&cbs, *in, len); - if (opt && !CBS_peek_asn1_tag(&cbs, CBS_ASN1_SEQUENCE)) { - return -1; +static int x509_parse_cb(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, + int opt) { + if (opt && !CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) { + return 1; } - X509 *ret = x509_parse(&cbs, NULL); - if (ret == NULL) { + bssl::UniquePtr ret = x509_parse(cbs); + if (ret == nullptr) { return 0; } - *in = CBS_data(&cbs); X509_free((X509 *)*pval); - *pval = (ASN1_VALUE *)ret; + *pval = (ASN1_VALUE *)ret.release(); return 1; } @@ -279,14 +365,9 @@ static int x509_i2d_cb(ASN1_VALUE **pval, unsigned char **out, return i2d_X509((X509 *)*pval, out); } -static const ASN1_EXTERN_FUNCS x509_extern_funcs = { - x509_new_cb, - x509_free_cb, - x509_d2i_cb, - x509_i2d_cb, -}; - -IMPLEMENT_EXTERN_ASN1(X509, V_ASN1_SEQUENCE, x509_extern_funcs) +static const ASN1_EXTERN_FUNCS x509_extern_funcs = {x509_new_cb, x509_free_cb, + x509_parse_cb, x509_i2d_cb}; +IMPLEMENT_EXTERN_ASN1(X509, x509_extern_funcs) X509 *X509_dup(X509 *x509) { uint8_t *der = NULL; @@ -301,18 +382,6 @@ X509 *X509_dup(X509 *x509) { return ret; } -X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) { - CBS cbs; - CBS_init(&cbs, CRYPTO_BUFFER_data(buf), CRYPTO_BUFFER_len(buf)); - X509 *ret = x509_parse(&cbs, buf); - if (ret == NULL || CBS_len(&cbs) != 0) { - X509_free(ret); - return NULL; - } - - return ret; -} - int X509_up_ref(X509 *x) { CRYPTO_refcount_inc(&x->references); return 1; @@ -437,49 +506,41 @@ int i2d_X509_AUX(X509 *a, unsigned char **pp) { } int i2d_re_X509_tbs(X509 *x509, unsigned char **outp) { - asn1_encoding_clear(&x509->cert_info->enc); - return i2d_X509_CINF(x509->cert_info, outp); + CRYPTO_BUFFER_free(x509->buf); + x509->buf = nullptr; + return i2d_X509_tbs(x509, outp); } int i2d_X509_tbs(X509 *x509, unsigned char **outp) { - return i2d_X509_CINF(x509->cert_info, outp); + return bssl::I2DFromCBB(/*initial_capacity=*/128, outp, [&](CBB *cbb) -> bool { + return x509_marshal_tbs_cert(cbb, x509); + }); } int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) { - X509_ALGOR *copy1 = X509_ALGOR_dup(algo); - X509_ALGOR *copy2 = X509_ALGOR_dup(algo); - if (copy1 == NULL || copy2 == NULL) { - X509_ALGOR_free(copy1); - X509_ALGOR_free(copy2); - return 0; - } - - X509_ALGOR_free(x509->sig_alg); - x509->sig_alg = copy1; - X509_ALGOR_free(x509->cert_info->signature); - x509->cert_info->signature = copy2; - return 1; + return X509_ALGOR_copy(&x509->sig_alg, algo) && + X509_ALGOR_copy(&x509->tbs_sig_alg, algo); } int X509_set1_signature_value(X509 *x509, const uint8_t *sig, size_t sig_len) { - if (!ASN1_STRING_set(x509->signature, sig, sig_len)) { + if (!ASN1_STRING_set(&x509->signature, sig, sig_len)) { return 0; } - x509->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - x509->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + x509->signature.flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + x509->signature.flags |= ASN1_STRING_FLAG_BITS_LEFT; return 1; } void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, const X509 *x) { if (psig) { - *psig = x->signature; + *psig = &x->signature; } if (palg) { - *palg = x->sig_alg; + *palg = &x->sig_alg; } } int X509_get_signature_nid(const X509 *x) { - return OBJ_obj2nid(x->sig_alg->algorithm); + return OBJ_obj2nid(x->sig_alg.algorithm); } diff --git a/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-apple.S b/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-apple.S index a79430850..2131b9006 100644 --- a/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-apple.S +++ b/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-apple.S @@ -7,11 +7,11 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64) && defined(__APPLE__) .text -.globl _bn_mul_mont -.private_extern _bn_mul_mont +.globl _bn_mul_mont_words +.private_extern _bn_mul_mont_words .align 5 -_bn_mul_mont: +_bn_mul_mont_words: AARCH64_SIGN_LINK_REGISTER tst x5,#7 b.eq __bn_sqr8x_mont @@ -217,7 +217,7 @@ Lcond_copy: .align 5 __bn_sqr8x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to - // only from bn_mul_mont which has already signed the return address. + // only from bn_mul_mont_words which has already signed the return address. cmp x1,x2 b.ne __bn_mul4x_mont Lsqr8x_mont: @@ -979,7 +979,7 @@ Lsqr8x_done: .align 5 __bn_mul4x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to - // only from bn_mul_mont or __bn_mul8x_mont which have already signed the + // only from bn_mul_mont_words or __bn_mul8x_mont which have already signed the // return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 diff --git a/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-linux.S b/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-linux.S index ab46c5b69..49281dbcf 100644 --- a/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-linux.S +++ b/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-linux.S @@ -7,11 +7,11 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64) && defined(__ELF__) .text -.globl bn_mul_mont -.hidden bn_mul_mont -.type bn_mul_mont,%function +.globl bn_mul_mont_words +.hidden bn_mul_mont_words +.type bn_mul_mont_words,%function .align 5 -bn_mul_mont: +bn_mul_mont_words: AARCH64_SIGN_LINK_REGISTER tst x5,#7 b.eq __bn_sqr8x_mont @@ -212,12 +212,12 @@ bn_mul_mont: ldr x29,[sp],#64 AARCH64_VALIDATE_LINK_REGISTER ret -.size bn_mul_mont,.-bn_mul_mont +.size bn_mul_mont_words,.-bn_mul_mont_words .type __bn_sqr8x_mont,%function .align 5 __bn_sqr8x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to - // only from bn_mul_mont which has already signed the return address. + // only from bn_mul_mont_words which has already signed the return address. cmp x1,x2 b.ne __bn_mul4x_mont .Lsqr8x_mont: @@ -979,7 +979,7 @@ __bn_sqr8x_mont: .align 5 __bn_mul4x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to - // only from bn_mul_mont or __bn_mul8x_mont which have already signed the + // only from bn_mul_mont_words or __bn_mul8x_mont which have already signed the // return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 diff --git a/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-win.S b/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-win.S index def7a92d9..c2b45f137 100644 --- a/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-win.S +++ b/Sources/CCryptoBoringSSL/gen/bcm/armv8-mont-win.S @@ -7,13 +7,13 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64) && defined(_WIN32) .text -.globl bn_mul_mont +.globl bn_mul_mont_words -.def bn_mul_mont +.def bn_mul_mont_words .type 32 .endef .align 5 -bn_mul_mont: +bn_mul_mont_words: AARCH64_SIGN_LINK_REGISTER tst x5,#7 b.eq __bn_sqr8x_mont @@ -221,7 +221,7 @@ Lcond_copy: .align 5 __bn_sqr8x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to - // only from bn_mul_mont which has already signed the return address. + // only from bn_mul_mont_words which has already signed the return address. cmp x1,x2 b.ne __bn_mul4x_mont Lsqr8x_mont: @@ -985,7 +985,7 @@ Lsqr8x_done: .align 5 __bn_mul4x_mont: // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to - // only from bn_mul_mont or __bn_mul8x_mont which have already signed the + // only from bn_mul_mont_words or __bn_mul8x_mont which have already signed the // return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 diff --git a/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-apple.S b/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-apple.S index 03b00eee5..8a05634e6 100644 --- a/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-apple.S +++ b/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-apple.S @@ -6,11 +6,11 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__APPLE__) .text -.globl _bn_mul_mont -.private_extern _bn_mul_mont +.globl _bn_mul_mont_words +.private_extern _bn_mul_mont_words .align 4 -_bn_mul_mont: -L_bn_mul_mont_begin: +_bn_mul_mont_words: +L_bn_mul_mont_words_begin: pushl %ebp pushl %ebx pushl %esi diff --git a/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-linux.S b/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-linux.S index 81cc896dc..37d96f457 100644 --- a/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-linux.S +++ b/Sources/CCryptoBoringSSL/gen/bcm/x86-mont-linux.S @@ -6,12 +6,12 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__ELF__) .text -.globl bn_mul_mont -.hidden bn_mul_mont -.type bn_mul_mont,@function +.globl bn_mul_mont_words +.hidden bn_mul_mont_words +.type bn_mul_mont_words,@function .align 16 -bn_mul_mont: -.L_bn_mul_mont_begin: +bn_mul_mont_words: +.L_bn_mul_mont_words_begin: pushl %ebp pushl %ebx pushl %esi @@ -210,7 +210,7 @@ bn_mul_mont: popl %ebx popl %ebp ret -.size bn_mul_mont,.-.L_bn_mul_mont_begin +.size bn_mul_mont_words,.-.L_bn_mul_mont_words_begin .byte 77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105 .byte 112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56 .byte 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121 diff --git a/Sources/CCryptoBoringSSL/gen/crypto/err_data.cc b/Sources/CCryptoBoringSSL/gen/crypto/err_data.cc index 2e00d9193..f14c40fc8 100644 --- a/Sources/CCryptoBoringSSL/gen/crypto/err_data.cc +++ b/Sources/CCryptoBoringSSL/gen/crypto/err_data.cc @@ -78,54 +78,54 @@ const uint32_t kOpenSSLReasonValues[] = { 0xc3b00f7, 0xc3b8921, 0x10320892, - 0x103296b2, - 0x103316be, - 0x103396d7, - 0x103416ea, + 0x103296ad, + 0x103316b9, + 0x103396d2, + 0x103416e5, 0x10348fd3, 0x10350d1f, - 0x103596fd, - 0x10361727, - 0x1036973a, - 0x10371759, - 0x10379772, - 0x10381787, - 0x103897a5, - 0x103917b4, - 0x103997d0, - 0x103a17eb, - 0x103a97fa, - 0x103b1816, - 0x103b9831, - 0x103c1857, + 0x103596f8, + 0x10361722, + 0x10369735, + 0x10371754, + 0x1037976d, + 0x10381782, + 0x103897a0, + 0x103917af, + 0x103997cb, + 0x103a17e6, + 0x103a97f5, + 0x103b1811, + 0x103b982c, + 0x103c1852, 0x103c80f7, - 0x103d1868, - 0x103d987c, - 0x103e189b, - 0x103e98aa, - 0x103f18c1, - 0x103f98d4, + 0x103d1863, + 0x103d9877, + 0x103e1896, + 0x103e98a5, + 0x103f18bc, + 0x103f98cf, 0x10400ce3, - 0x104098e7, - 0x10411905, - 0x10419918, - 0x10421932, - 0x10429942, - 0x10431956, - 0x1043996c, - 0x10441984, - 0x10449999, - 0x104519ad, - 0x104599bf, + 0x104098e2, + 0x10411900, + 0x10419913, + 0x1042192d, + 0x1042993d, + 0x10431951, + 0x10439967, + 0x1044197f, + 0x10449994, + 0x104519a8, + 0x104599ba, 0x10460635, 0x1046899a, - 0x104719d4, - 0x104799eb, - 0x10481a00, - 0x10489a0e, + 0x104719cf, + 0x104799e6, + 0x104819fb, + 0x10489a09, 0x10490f1f, - 0x10499848, - 0x104a1712, + 0x10499843, + 0x104a170d, 0x14320cb3, 0x14328cd4, 0x14330ce3, @@ -139,57 +139,57 @@ const uint32_t kOpenSSLReasonValues[] = { 0x1833903f, 0x18341053, 0x183480f7, - 0x18351072, - 0x1835908a, - 0x183610b2, - 0x183690c6, - 0x183710fe, - 0x18379114, - 0x18381128, - 0x18389138, + 0x183510ae, + 0x18359072, + 0x1836109a, + 0x183690c1, + 0x183710f9, + 0x1837910f, + 0x18381123, + 0x18389133, 0x18390ac0, - 0x18399148, - 0x183a116e, - 0x183a9194, + 0x18399143, + 0x183a1169, + 0x183a918f, 0x183b0d2b, - 0x183b91e3, - 0x183c11f5, - 0x183c9200, - 0x183d1210, - 0x183d9221, - 0x183e1232, - 0x183e9244, - 0x183f126d, - 0x183f9286, - 0x1840129e, + 0x183b91de, + 0x183c11f0, + 0x183c91fb, + 0x183d120b, + 0x183d921c, + 0x183e122d, + 0x183e923f, + 0x183f1268, + 0x183f9281, + 0x18401299, 0x1840870d, - 0x184111b7, - 0x18419182, - 0x184211a1, + 0x184111b2, + 0x1841917d, + 0x1842119c, 0x18428cc1, - 0x1843115d, - 0x184391c9, + 0x18431158, + 0x184391c4, 0x18441068, - 0x184490ea, - 0x1845109f, - 0x203212d8, - 0x203292c5, - 0x243212e4, + 0x184490e5, + 0x18451087, + 0x203212d3, + 0x203292c0, + 0x243212df, 0x243289e0, - 0x243312f6, - 0x24339303, - 0x24341310, - 0x24349322, - 0x24351331, - 0x2435934e, - 0x2436135b, - 0x24369369, - 0x24371377, - 0x24379385, - 0x2438138e, - 0x2438939b, - 0x243913ae, - 0x243993c5, + 0x243312f1, + 0x243392fe, + 0x2434130b, + 0x2434931d, + 0x2435132c, + 0x24359349, + 0x24361356, + 0x24369364, + 0x24371372, + 0x24379380, + 0x24381389, + 0x24389396, + 0x243913a9, + 0x243993c0, 0x28320d13, 0x28328d2b, 0x28330ce3, @@ -199,51 +199,51 @@ const uint32_t kOpenSSLReasonValues[] = { 0x283500f7, 0x28358cc1, 0x2836099a, - 0x2c3233f9, - 0x2c3293e3, - 0x2c333407, - 0x2c33b419, - 0x2c34342d, - 0x2c34b43f, - 0x2c35345a, - 0x2c35b46c, - 0x2c36349c, + 0x2c3233f4, + 0x2c3293de, + 0x2c333402, + 0x2c33b414, + 0x2c343428, + 0x2c34b43a, + 0x2c353455, + 0x2c35b467, + 0x2c363497, 0x2c36833a, - 0x2c3734a9, - 0x2c37b4d5, - 0x2c383513, - 0x2c38b52a, - 0x2c393548, - 0x2c39b558, - 0x2c3a356a, - 0x2c3ab57e, - 0x2c3b358f, - 0x2c3bb5ae, - 0x2c3c13f5, - 0x2c3c940b, - 0x2c3d35f3, - 0x2c3d9424, - 0x2c3e361d, - 0x2c3eb62b, - 0x2c3f3643, - 0x2c3fb65b, - 0x2c403685, - 0x2c4092d8, - 0x2c413696, - 0x2c41b6a9, - 0x2c42129e, - 0x2c42b6ba, + 0x2c3734a4, + 0x2c37b4d0, + 0x2c38350e, + 0x2c38b525, + 0x2c393543, + 0x2c39b553, + 0x2c3a3565, + 0x2c3ab579, + 0x2c3b358a, + 0x2c3bb5a9, + 0x2c3c13f0, + 0x2c3c9406, + 0x2c3d35ee, + 0x2c3d941f, + 0x2c3e3618, + 0x2c3eb626, + 0x2c3f363e, + 0x2c3fb656, + 0x2c403680, + 0x2c4092d3, + 0x2c413691, + 0x2c41b6a4, + 0x2c421299, + 0x2c42b6b5, 0x2c43076d, - 0x2c43b5a0, - 0x2c4434e8, - 0x2c44b668, - 0x2c45347f, - 0x2c45b4bb, - 0x2c463538, - 0x2c46b5c2, - 0x2c4735d7, - 0x2c47b610, - 0x2c4834fa, + 0x2c43b59b, + 0x2c4434e3, + 0x2c44b663, + 0x2c45347a, + 0x2c45b4b6, + 0x2c463533, + 0x2c46b5bd, + 0x2c4735d2, + 0x2c47b60b, + 0x2c4834f5, 0x30320000, 0x30328015, 0x3033001f, @@ -383,268 +383,268 @@ const uint32_t kOpenSSLReasonValues[] = { 0x3c418e13, 0x3c420f1f, 0x3c428ea9, - 0x40321a7a, - 0x40329a90, - 0x40331abe, - 0x40339ac8, - 0x40341adf, - 0x40349afd, - 0x40351b0d, - 0x40359b1f, - 0x40361b2c, - 0x40369b38, - 0x40371b4d, - 0x40379b5f, - 0x40381b6a, - 0x40389b7c, + 0x40321a75, + 0x40329a8b, + 0x40331ab9, + 0x40339ac3, + 0x40341ada, + 0x40349af8, + 0x40351b08, + 0x40359b1a, + 0x40361b27, + 0x40369b33, + 0x40371b48, + 0x40379b5a, + 0x40381b65, + 0x40389b77, 0x40390fd3, - 0x40399b8c, - 0x403a1b9f, - 0x403a9bc0, - 0x403b1bd1, - 0x403b9be1, + 0x40399b87, + 0x403a1b9a, + 0x403a9bbb, + 0x403b1bcc, + 0x403b9bdc, 0x403c0071, 0x403c8090, - 0x403d1c42, - 0x403d9c58, - 0x403e1c67, - 0x403e9c9f, - 0x403f1cb9, - 0x403f9ce1, - 0x40401cf6, - 0x40409d0a, - 0x40411d45, - 0x40419d60, - 0x40421d79, - 0x40429d8c, - 0x40431da0, - 0x40439dce, - 0x40441de5, + 0x403d1c3d, + 0x403d9c53, + 0x403e1c62, + 0x403e9c9a, + 0x403f1cb4, + 0x403f9cdc, + 0x40401cf1, + 0x40409d05, + 0x40411d40, + 0x40419d5b, + 0x40421d74, + 0x40429d87, + 0x40431d9b, + 0x40439dc9, + 0x40441de0, 0x404480b9, - 0x40451dfa, - 0x40459e0c, - 0x40461e30, - 0x40469e50, - 0x40471e5e, - 0x40479e85, - 0x40481ef6, - 0x40489fb0, - 0x40491fc7, - 0x40499fe1, - 0x404a1ff8, - 0x404aa016, - 0x404b202e, - 0x404ba05b, - 0x404c2071, - 0x404ca083, - 0x404d20a4, - 0x404da0dd, - 0x404e20f1, - 0x404ea0fe, - 0x404f21af, - 0x404fa225, - 0x405022af, - 0x4050a2c3, - 0x405122f6, - 0x40522306, - 0x4052a32a, - 0x40532342, - 0x4053a355, - 0x4054236a, - 0x4054a38d, - 0x405523b8, - 0x4055a3f5, - 0x4056241a, - 0x4056a433, - 0x4057244b, - 0x4057a45e, - 0x40582473, - 0x4058a49a, - 0x405924c9, - 0x4059a509, - 0x405aa51d, - 0x405b2535, - 0x405ba546, - 0x405c2559, - 0x405ca598, - 0x405d25a5, - 0x405da5ca, - 0x405e2608, + 0x40451df5, + 0x40459e07, + 0x40461e2b, + 0x40469e4b, + 0x40471e59, + 0x40479e80, + 0x40481ef1, + 0x40489fab, + 0x40491fc2, + 0x40499fdc, + 0x404a1ff3, + 0x404aa011, + 0x404b2029, + 0x404ba056, + 0x404c206c, + 0x404ca07e, + 0x404d209f, + 0x404da0d8, + 0x404e20ec, + 0x404ea0f9, + 0x404f21aa, + 0x404fa220, + 0x405022aa, + 0x4050a2be, + 0x405122f1, + 0x40522301, + 0x4052a325, + 0x4053233d, + 0x4053a350, + 0x40542365, + 0x4054a388, + 0x405523b3, + 0x4055a3f0, + 0x40562415, + 0x4056a42e, + 0x40572446, + 0x4057a459, + 0x4058246e, + 0x4058a495, + 0x405924c4, + 0x4059a504, + 0x405aa518, + 0x405b2530, + 0x405ba541, + 0x405c2554, + 0x405ca593, + 0x405d25a0, + 0x405da5c5, + 0x405e2603, 0x405e8afe, - 0x405f2657, - 0x405fa664, - 0x40602672, - 0x4060a694, - 0x40612708, - 0x4061a740, - 0x40622757, - 0x4062a768, - 0x406327b5, - 0x4063a7ca, - 0x406427e1, - 0x4064a80d, - 0x40652828, - 0x4065a83f, - 0x40662857, - 0x4066a881, - 0x406728ac, - 0x4067a8f1, - 0x40682939, - 0x4068a95a, - 0x4069298c, - 0x4069a9ba, - 0x406a29db, - 0x406aa9fb, - 0x406b2b83, - 0x406baba6, - 0x406c2bbc, - 0x406caec6, - 0x406d2ef5, - 0x406daf1d, - 0x406e2f4b, - 0x406eaf98, - 0x406f2ff1, - 0x406fb029, - 0x4070303c, - 0x4070b059, + 0x405f2652, + 0x405fa65f, + 0x4060266d, + 0x4060a68f, + 0x40612703, + 0x4061a73b, + 0x40622752, + 0x4062a763, + 0x406327b0, + 0x4063a7c5, + 0x406427dc, + 0x4064a808, + 0x40652823, + 0x4065a83a, + 0x40662852, + 0x4066a87c, + 0x406728a7, + 0x4067a8ec, + 0x40682934, + 0x4068a955, + 0x40692987, + 0x4069a9b5, + 0x406a29d6, + 0x406aa9f6, + 0x406b2b7e, + 0x406baba1, + 0x406c2bb7, + 0x406caec1, + 0x406d2ef0, + 0x406daf18, + 0x406e2f46, + 0x406eaf93, + 0x406f2fec, + 0x406fb024, + 0x40703037, + 0x4070b054, 0x4071084d, - 0x4071b06b, - 0x4072307e, - 0x4072b0b4, - 0x407330cc, - 0x4073960d, - 0x407430e0, - 0x4074b0fa, - 0x4075310b, - 0x4075b11f, - 0x4076312d, - 0x4076939b, - 0x40773152, - 0x4077b1ea, - 0x40783205, - 0x4078b23e, - 0x40793255, - 0x4079b26b, - 0x407a3297, - 0x407ab2aa, - 0x407b32bf, - 0x407bb2d1, - 0x407c3302, - 0x407cb30b, - 0x407d2975, - 0x407da24d, - 0x407e321a, - 0x407ea4aa, - 0x407f1e72, - 0x407fa045, - 0x408021bf, - 0x40809e9a, - 0x40812318, - 0x4081a14c, - 0x40822f36, - 0x40829bed, - 0x40832485, - 0x4083a7f2, - 0x40841eae, - 0x4084a4e2, - 0x4085256a, - 0x4085a6cf, - 0x408625ea, - 0x4086a267, - 0x40872f7c, - 0x4087a71d, - 0x40881c2b, - 0x4088a904, - 0x40891c7a, - 0x40899c07, - 0x408a2bf4, - 0x408a9a25, - 0x408b32e6, - 0x408bb006, - 0x408c257a, - 0x408d1f96, - 0x408d9ee0, - 0x408e20c6, - 0x408ea3d5, - 0x408f2918, - 0x408fa6eb, - 0x409028cd, - 0x4090a5bc, - 0x40912bdc, - 0x40919a5d, - 0x40921cc7, - 0x4092afb7, - 0x40933097, - 0x4093a278, - 0x40941ec2, - 0x4094ac0d, - 0x40952779, - 0x4095b277, - 0x40962f63, - 0x4096a1d8, - 0x409722de, - 0x4097a115, - 0x40981d27, - 0x4098a78d, - 0x40992fd3, - 0x4099a402, - 0x409a239b, - 0x409a9a41, - 0x409b1f1c, - 0x409b9f47, - 0x409c31cc, - 0x409c9f6f, - 0x409d2194, - 0x409da162, - 0x409e1db8, - 0x409ea20d, - 0x409f21f5, - 0x409f9f0f, - 0x40a02235, - 0x40a0a12f, - 0x40a1217d, - 0x40a1a4f6, - 0x40a22294, - 0x40a2a648, - 0x40a326bc, - 0x40a3b174, - 0x40a43190, - 0x40a4b1aa, - 0x41f42aae, - 0x41f92b40, - 0x41fe2a33, - 0x41feace9, - 0x41ff2e17, - 0x42032ac7, - 0x42082ae9, - 0x4208ab25, - 0x42092a17, - 0x4209ab5f, - 0x420a2a6e, - 0x420aaa4e, - 0x420b2a8e, - 0x420bab07, - 0x420c2e33, - 0x420cac1d, - 0x420d2cd0, - 0x420dad07, - 0x42122d3a, - 0x42172dfa, - 0x4217ad7c, - 0x421c2d9e, - 0x421f2d59, - 0x42212eab, - 0x42262ddd, - 0x422b2e89, - 0x422bacab, - 0x422c2e6b, - 0x422cac5e, - 0x422d2c37, - 0x422dae4a, - 0x422e2c8a, - 0x42302db9, - 0x4230ad21, - 0x42312629, + 0x4071b066, + 0x40723079, + 0x4072b0af, + 0x407330c7, + 0x40739608, + 0x407430db, + 0x4074b0f5, + 0x40753106, + 0x4075b11a, + 0x40763128, + 0x40769396, + 0x4077314d, + 0x4077b1e5, + 0x40783200, + 0x4078b239, + 0x40793250, + 0x4079b266, + 0x407a3292, + 0x407ab2a5, + 0x407b32ba, + 0x407bb2cc, + 0x407c32fd, + 0x407cb306, + 0x407d2970, + 0x407da248, + 0x407e3215, + 0x407ea4a5, + 0x407f1e6d, + 0x407fa040, + 0x408021ba, + 0x40809e95, + 0x40812313, + 0x4081a147, + 0x40822f31, + 0x40829be8, + 0x40832480, + 0x4083a7ed, + 0x40841ea9, + 0x4084a4dd, + 0x40852565, + 0x4085a6ca, + 0x408625e5, + 0x4086a262, + 0x40872f77, + 0x4087a718, + 0x40881c26, + 0x4088a8ff, + 0x40891c75, + 0x40899c02, + 0x408a2bef, + 0x408a9a20, + 0x408b32e1, + 0x408bb001, + 0x408c2575, + 0x408d1f91, + 0x408d9edb, + 0x408e20c1, + 0x408ea3d0, + 0x408f2913, + 0x408fa6e6, + 0x409028c8, + 0x4090a5b7, + 0x40912bd7, + 0x40919a58, + 0x40921cc2, + 0x4092afb2, + 0x40933092, + 0x4093a273, + 0x40941ebd, + 0x4094ac08, + 0x40952774, + 0x4095b272, + 0x40962f5e, + 0x4096a1d3, + 0x409722d9, + 0x4097a110, + 0x40981d22, + 0x4098a788, + 0x40992fce, + 0x4099a3fd, + 0x409a2396, + 0x409a9a3c, + 0x409b1f17, + 0x409b9f42, + 0x409c31c7, + 0x409c9f6a, + 0x409d218f, + 0x409da15d, + 0x409e1db3, + 0x409ea208, + 0x409f21f0, + 0x409f9f0a, + 0x40a02230, + 0x40a0a12a, + 0x40a12178, + 0x40a1a4f1, + 0x40a2228f, + 0x40a2a643, + 0x40a326b7, + 0x40a3b16f, + 0x40a4318b, + 0x40a4b1a5, + 0x41f42aa9, + 0x41f92b3b, + 0x41fe2a2e, + 0x41feace4, + 0x41ff2e12, + 0x42032ac2, + 0x42082ae4, + 0x4208ab20, + 0x42092a12, + 0x4209ab5a, + 0x420a2a69, + 0x420aaa49, + 0x420b2a89, + 0x420bab02, + 0x420c2e2e, + 0x420cac18, + 0x420d2ccb, + 0x420dad02, + 0x42122d35, + 0x42172df5, + 0x4217ad77, + 0x421c2d99, + 0x421f2d54, + 0x42212ea6, + 0x42262dd8, + 0x422b2e84, + 0x422baca6, + 0x422c2e66, + 0x422cac59, + 0x422d2c32, + 0x422dae45, + 0x422e2c85, + 0x42302db4, + 0x4230ad1c, + 0x42312624, 0x44320778, 0x44328787, 0x44330793, @@ -662,109 +662,109 @@ const uint32_t kOpenSSLReasonValues[] = { 0x4439084d, 0x4439885b, 0x443a086e, - 0x483213e3, - 0x483293f5, - 0x4833140b, - 0x48339424, - 0x4c321461, - 0x4c329471, - 0x4c331484, - 0x4c3394a4, + 0x483213de, + 0x483293f0, + 0x48331406, + 0x4833941f, + 0x4c32145c, + 0x4c32946c, + 0x4c33147f, + 0x4c33949f, 0x4c3400b9, 0x4c3480f7, - 0x4c3514b0, - 0x4c3594be, - 0x4c3614da, - 0x4c369500, - 0x4c37150f, - 0x4c37951d, - 0x4c381532, - 0x4c38953e, - 0x4c39155e, - 0x4c399588, - 0x4c3a15a1, - 0x4c3a95ba, + 0x4c3514ab, + 0x4c3594b9, + 0x4c3614d5, + 0x4c3694fb, + 0x4c37150a, + 0x4c379518, + 0x4c38152d, + 0x4c389539, + 0x4c391559, + 0x4c399583, + 0x4c3a159c, + 0x4c3a95b5, 0x4c3b0635, - 0x4c3b95d3, - 0x4c3c15e5, - 0x4c3c95f4, - 0x4c3d160d, + 0x4c3b95ce, + 0x4c3c15e0, + 0x4c3c95ef, + 0x4c3d1608, 0x4c3d8d06, - 0x4c3e167a, - 0x4c3e961c, - 0x4c3f169c, - 0x4c3f939b, - 0x4c401632, - 0x4c40944d, - 0x4c41166a, - 0x4c4194ed, - 0x4c421656, - 0x4c429435, - 0x503236cc, - 0x5032b6db, - 0x503336e6, - 0x5033b6f6, - 0x5034370f, - 0x5034b729, - 0x50353737, - 0x5035b74d, - 0x5036375f, - 0x5036b775, - 0x5037378e, - 0x5037b7a1, - 0x503837b9, - 0x5038b7ca, - 0x503937df, - 0x5039b7f3, - 0x503a3813, - 0x503ab829, - 0x503b3841, - 0x503bb853, - 0x503c386f, - 0x503cb886, - 0x503d389f, - 0x503db8b5, - 0x503e38c2, - 0x503eb8d8, - 0x503f38ea, + 0x4c3e1675, + 0x4c3e9617, + 0x4c3f1697, + 0x4c3f9396, + 0x4c40162d, + 0x4c409448, + 0x4c411665, + 0x4c4194e8, + 0x4c421651, + 0x4c429430, + 0x503236c7, + 0x5032b6d6, + 0x503336e1, + 0x5033b6f1, + 0x5034370a, + 0x5034b724, + 0x50353732, + 0x5035b748, + 0x5036375a, + 0x5036b770, + 0x50373789, + 0x5037b79c, + 0x503837b4, + 0x5038b7c5, + 0x503937da, + 0x5039b7ee, + 0x503a380e, + 0x503ab824, + 0x503b383c, + 0x503bb84e, + 0x503c386a, + 0x503cb881, + 0x503d389a, + 0x503db8b0, + 0x503e38bd, + 0x503eb8d3, + 0x503f38e5, 0x503f83b3, - 0x504038fd, - 0x5040b90d, - 0x50413927, - 0x5041b936, - 0x50423950, - 0x5042b96d, - 0x5043397d, - 0x5043b98d, - 0x504439aa, + 0x504038f8, + 0x5040b908, + 0x50413922, + 0x5041b931, + 0x5042394b, + 0x5042b968, + 0x50433978, + 0x5043b988, + 0x504439a5, 0x50448469, - 0x504539be, - 0x5045b9dc, - 0x504639ef, - 0x5046ba05, - 0x50473a17, - 0x5047ba2c, - 0x50483a52, - 0x5048ba60, - 0x50493a73, - 0x5049ba88, - 0x504a3a9e, - 0x504abaae, - 0x504b3ace, - 0x504bbae1, - 0x504c3b04, - 0x504cbb32, - 0x504d3b5f, - 0x504dbb7c, - 0x504e3b97, - 0x504ebbb3, - 0x504f3bc5, - 0x504fbbdc, - 0x50503beb, + 0x504539b9, + 0x5045b9d7, + 0x504639ea, + 0x5046ba00, + 0x50473a12, + 0x5047ba27, + 0x50483a4d, + 0x5048ba5b, + 0x50493a6e, + 0x5049ba83, + 0x504a3a99, + 0x504abaa9, + 0x504b3ac9, + 0x504bbadc, + 0x504c3aff, + 0x504cbb2d, + 0x504d3b5a, + 0x504dbb77, + 0x504e3b92, + 0x504ebbae, + 0x504f3bc0, + 0x504fbbd7, + 0x50503be6, 0x50508729, - 0x50513bfe, - 0x5051b99c, - 0x50523b44, + 0x50513bf9, + 0x5051b997, + 0x50523b3f, 0x58321011, 0x68320fd3, 0x68328d2b, @@ -806,22 +806,22 @@ const uint32_t kOpenSSLReasonValues[] = { 0x783d8b97, 0x783e0aed, 0x783e8a9f, - 0x7c3212b4, - 0x80321500, + 0x7c3212af, + 0x803214fb, 0x80328090, - 0x803333c8, + 0x803333c3, 0x803380b9, - 0x803433d7, - 0x8034b33f, - 0x8035335d, - 0x8035b3eb, - 0x8036339f, - 0x8036b34e, - 0x80373391, - 0x8037b32c, - 0x803833b2, - 0x8038b36e, - 0x80393383, + 0x803433d2, + 0x8034b33a, + 0x80353358, + 0x8035b3e6, + 0x8036339a, + 0x8036b349, + 0x8037338c, + 0x8037b327, + 0x803833ad, + 0x8038b369, + 0x8039337e, 0x84320bb0, 0x84328bc9, }; @@ -1049,10 +1049,10 @@ const char kOpenSSLReasonStringData[] = "DIFFERENT_KEY_TYPES\0" "DIFFERENT_PARAMETERS\0" "EMPTY_PSK\0" - "EXPECTING_AN_EC_KEY_KEY\0" "EXPECTING_AN_RSA_KEY\0" "EXPECTING_A_DH_KEY\0" "EXPECTING_A_DSA_KEY\0" + "EXPECTING_A_EC_KEY\0" "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0" "INVALID_BUFFER_SIZE\0" "INVALID_DIGEST_LENGTH\0" diff --git a/Sources/CCryptoBoringSSL/hash.txt b/Sources/CCryptoBoringSSL/hash.txt index 60ae1b489..d3430aebc 100644 --- a/Sources/CCryptoBoringSSL/hash.txt +++ b/Sources/CCryptoBoringSSL/hash.txt @@ -1 +1 @@ -This directory is derived from BoringSSL cloned from https://boringssl.googlesource.com/boringssl at revision 035e720641f385e82c72b7b0a9e1d89e58cb5ed5 +This directory is derived from BoringSSL cloned from https://boringssl.googlesource.com/boringssl at revision 0226f30467f540a3f62ef48d453f93927da199b6 diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1.h index a5791995a..b9368dcc8 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1.h @@ -801,10 +801,6 @@ OPENSSL_EXPORT ASN1_STRING *d2i_DIRECTORYSTRING(ASN1_STRING **out, // 5280), as described in |i2d_SAMPLE|. OPENSSL_EXPORT int i2d_DIRECTORYSTRING(const ASN1_STRING *in, uint8_t **outp); -// DIRECTORYSTRING is an |ASN1_ITEM| whose ASN.1 type is X.509 DirectoryString -// (RFC 5280) and C type is |ASN1_STRING*|. -DECLARE_ASN1_ITEM(DIRECTORYSTRING) - // B_ASN1_DISPLAYTEXT is a bitmask of types allowed in an X.509 DisplayText (RFC // 5280). #define B_ASN1_DISPLAYTEXT \ @@ -834,10 +830,6 @@ OPENSSL_EXPORT ASN1_STRING *d2i_DISPLAYTEXT(ASN1_STRING **out, // as described in |i2d_SAMPLE|. OPENSSL_EXPORT int i2d_DISPLAYTEXT(const ASN1_STRING *in, uint8_t **outp); -// DISPLAYTEXT is an |ASN1_ITEM| whose ASN.1 type is X.509 DisplayText (RFC -// 5280) and C type is |ASN1_STRING*|. -DECLARE_ASN1_ITEM(DISPLAYTEXT) - // Bit strings. // @@ -1258,10 +1250,6 @@ OPENSSL_EXPORT ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **out, const uint8_t **inp, // described in |i2d_SAMPLE|. OPENSSL_EXPORT int i2d_ASN1_TIME(const ASN1_TIME *in, uint8_t **outp); -// ASN1_TIME is an |ASN1_ITEM| whose ASN.1 type is X.509 Time (RFC 5280) and C -// type is |ASN1_TIME*|. -DECLARE_ASN1_ITEM(ASN1_TIME) - // ASN1_TIME_diff computes |to| - |from|. On success, it sets |*out_days| to the // difference in days, rounded towards zero, sets |*out_seconds| to the // remainder, and returns one. On error, it returns zero. diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1t.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1t.h index 92f1d66d6..24c7860b6 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1t.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_asn1t.h @@ -491,8 +491,8 @@ typedef struct ASN1_AUX_st { ASN1_ITEM_start(itname) ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, \ sizeof(ASN1_STRING), #itname ASN1_ITEM_end(itname) -#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ - ASN1_ITEM_start(sname) ASN1_ITYPE_EXTERN, tag, NULL, 0, &fptrs, 0, \ +#define IMPLEMENT_EXTERN_ASN1(sname, fptrs) \ + ASN1_ITEM_start(sname) ASN1_ITYPE_EXTERN, -1, NULL, 0, &fptrs, 0, \ #sname ASN1_ITEM_end(sname) /* Macro to implement standard functions in terms of ASN1_ITEM structures */ diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_base.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_base.h index 66f2c2eae..676d7868e 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_base.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_base.h @@ -335,6 +335,7 @@ typedef struct evp_hpke_ctx_st EVP_HPKE_CTX; typedef struct evp_hpke_kdf_st EVP_HPKE_KDF; typedef struct evp_hpke_kem_st EVP_HPKE_KEM; typedef struct evp_hpke_key_st EVP_HPKE_KEY; +typedef struct evp_pkey_alg_st EVP_PKEY_ALG; typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; typedef struct evp_pkey_st EVP_PKEY; typedef struct hmac_ctx_st HMAC_CTX; diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bcm_public.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bcm_public.h index 0b0d62edd..4b6db8b8f 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bcm_public.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bcm_public.h @@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_BCM_PUBLIC_H_ #define OPENSSL_HEADER_BCM_PUBLIC_H_ -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -69,9 +69,10 @@ struct sha256_state_st { struct sha512_state_st { uint64_t h[8]; - uint64_t Nl, Nh; + uint16_t num, md_len; + uint32_t bytes_so_far_high; + uint64_t bytes_so_far_low; uint8_t p[BCM_SHA512_CBLOCK]; - unsigned num, md_len; }; diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_blake2.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_blake2.h index fa549e307..c0fe056cb 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_blake2.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_blake2.h @@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_BLAKE2_H #define OPENSSL_HEADER_BLAKE2_H -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -27,9 +27,10 @@ extern "C" { struct blake2b_state_st { uint64_t h[8]; - uint64_t t_low, t_high; + uint64_t t_low; + uint32_t t_high; + uint32_t block_used; uint8_t block[BLAKE2B_CBLOCK]; - size_t block_used; }; // BLAKE2B256_Init initialises |b2b| to perform a BLAKE2b-256 hash. There are no diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bn.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bn.h index b5a165860..87fc5f7f0 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bn.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_bn.h @@ -916,16 +916,6 @@ struct bignum_st { int flags; }; -struct bn_mont_ctx_st { - // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form. It - // is guaranteed to have the same width as |N|. - BIGNUM RR; - // N is the modulus. It is always stored in minimal form, so |N.width| - // determines R. - BIGNUM N; - BN_ULONG n0[2]; // least significant words of (R*Ri-1)/N -}; - OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l); #define BN_FLG_MALLOCED 0x01 diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h index 8b97b726b..bda146a92 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols.h @@ -165,8 +165,12 @@ #define ASN1_item_sign_ctx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_item_sign_ctx) #define ASN1_item_unpack BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_item_unpack) #define ASN1_item_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_item_verify) +#define asn1_marshal_any BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_marshal_any) #define asn1_marshal_bit_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_marshal_bit_string) #define asn1_marshal_integer BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_marshal_integer) +#define asn1_marshal_object BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_marshal_object) +#define asn1_marshal_octet_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_marshal_octet_string) +#define asn1_marshal_time BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_marshal_time) #define ASN1_mbstring_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_mbstring_copy) #define ASN1_mbstring_ncopy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_mbstring_ncopy) #define ASN1_NULL_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_NULL_free) @@ -183,6 +187,20 @@ #define ASN1_OCTET_STRING_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_OCTET_STRING_it) #define ASN1_OCTET_STRING_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_OCTET_STRING_new) #define ASN1_OCTET_STRING_set BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_OCTET_STRING_set) +#define asn1_parse_any BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_any) +#define asn1_parse_any_as_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_any_as_string) +#define asn1_parse_bit_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_bit_string) +#define asn1_parse_bit_string_with_bad_length BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_bit_string_with_bad_length) +#define asn1_parse_bmp_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_bmp_string) +#define asn1_parse_enumerated BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_enumerated) +#define asn1_parse_generalized_time BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_generalized_time) +#define asn1_parse_integer BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_integer) +#define asn1_parse_object BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_object) +#define asn1_parse_octet_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_octet_string) +#define asn1_parse_time BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_time) +#define asn1_parse_universal_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_universal_string) +#define asn1_parse_utc_time BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_utc_time) +#define asn1_parse_utf8_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_parse_utf8_string) #define ASN1_primitive_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_primitive_free) #define ASN1_PRINTABLESTRING_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_PRINTABLESTRING_free) #define ASN1_PRINTABLESTRING_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_PRINTABLESTRING_it) @@ -193,6 +211,7 @@ #define asn1_refcount_set_one BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_refcount_set_one) #define ASN1_SEQUENCE_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_SEQUENCE_it) #define asn1_set_choice_selector BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_set_choice_selector) +#define asn1_string_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_string_cleanup) #define ASN1_STRING_cmp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_cmp) #define ASN1_STRING_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_copy) #define ASN1_STRING_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_data) @@ -200,6 +219,7 @@ #define ASN1_STRING_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_free) #define ASN1_STRING_get_default_mask BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_get_default_mask) #define ASN1_STRING_get0_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_get0_data) +#define asn1_string_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_string_init) #define ASN1_STRING_length BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_length) #define ASN1_STRING_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_new) #define ASN1_STRING_print BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ASN1_STRING_print) @@ -280,6 +300,26 @@ #define bcm_as_approved_status BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bcm_as_approved_status) #define bcm_as_not_approved_status BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bcm_as_not_approved_status) #define BCM_fips_186_2_prf BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_fips_186_2_prf) +#define BCM_mldsa44_check_key_fips BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_check_key_fips) +#define BCM_mldsa44_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_generate_key) +#define BCM_mldsa44_generate_key_external_entropy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_generate_key_external_entropy) +#define BCM_mldsa44_generate_key_external_entropy_fips BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_generate_key_external_entropy_fips) +#define BCM_mldsa44_generate_key_fips BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_generate_key_fips) +#define BCM_mldsa44_marshal_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_marshal_private_key) +#define BCM_mldsa44_marshal_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_marshal_public_key) +#define BCM_mldsa44_parse_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_parse_private_key) +#define BCM_mldsa44_parse_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_parse_public_key) +#define BCM_mldsa44_prehash_finalize BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_prehash_finalize) +#define BCM_mldsa44_prehash_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_prehash_init) +#define BCM_mldsa44_prehash_update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_prehash_update) +#define BCM_mldsa44_private_key_from_seed BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_private_key_from_seed) +#define BCM_mldsa44_private_key_from_seed_fips BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_private_key_from_seed_fips) +#define BCM_mldsa44_public_from_private BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_public_from_private) +#define BCM_mldsa44_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_sign) +#define BCM_mldsa44_sign_internal BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_sign_internal) +#define BCM_mldsa44_sign_message_representative BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_sign_message_representative) +#define BCM_mldsa44_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_verify) +#define BCM_mldsa44_verify_internal BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa44_verify_internal) #define BCM_mldsa65_check_key_fips BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa65_check_key_fips) #define BCM_mldsa65_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa65_generate_key) #define BCM_mldsa65_generate_key_external_entropy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BCM_mldsa65_generate_key_external_entropy) @@ -630,9 +670,9 @@ #define bn_mul_comba4 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_comba4) #define bn_mul_comba8 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_comba8) #define bn_mul_consttime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_consttime) -#define bn_mul_mont BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_mont) #define bn_mul_mont_gather5_nohw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_mont_gather5_nohw) #define bn_mul_mont_nohw BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_mont_nohw) +#define bn_mul_mont_words BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_mont_words) #define bn_mul_small BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_small) #define BN_mul_word BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, BN_mul_word) #define bn_mul_words BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bn_mul_words) @@ -880,6 +920,7 @@ #define CMS_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CMS_sign) #define CONF_modules_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CONF_modules_free) #define CONF_modules_load_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CONF_modules_load_file) +#define CONF_modules_unload BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CONF_modules_unload) #define CONF_parse_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CONF_parse_list) #define CONF_VALUE_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CONF_VALUE_new) #define CRL_DIST_POINTS_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRL_DIST_POINTS_free) @@ -1014,7 +1055,9 @@ #define CTR_DRBG_generate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_generate) #define CTR_DRBG_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_init) #define CTR_DRBG_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_new) +#define CTR_DRBG_new_df BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_new_df) #define CTR_DRBG_reseed BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_reseed) +#define CTR_DRBG_reseed_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CTR_DRBG_reseed_ex) #define d2i_ASN1_BIT_STRING BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_ASN1_BIT_STRING) #define d2i_ASN1_BMPSTRING BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_ASN1_BMPSTRING) #define d2i_ASN1_BOOLEAN BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_ASN1_BOOLEAN) @@ -1105,7 +1148,6 @@ #define d2i_X509_AUX BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_AUX) #define d2i_X509_bio BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_bio) #define d2i_X509_CERT_AUX BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_CERT_AUX) -#define d2i_X509_CINF BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_CINF) #define d2i_X509_CRL BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_CRL) #define d2i_X509_CRL_bio BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_CRL_bio) #define d2i_X509_CRL_fp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_CRL_fp) @@ -1121,7 +1163,6 @@ #define d2i_X509_REQ_INFO BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_REQ_INFO) #define d2i_X509_REVOKED BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_REVOKED) #define d2i_X509_SIG BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_SIG) -#define d2i_X509_VAL BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, d2i_X509_VAL) #define DES_decrypt3 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DES_decrypt3) #define DES_ecb_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DES_ecb_encrypt) #define DES_ecb_encrypt_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DES_ecb_encrypt_ex) @@ -1329,8 +1370,11 @@ #define EC_KEY_new_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_new_method) #define EC_KEY_oct2key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_oct2key) #define EC_KEY_oct2priv BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_oct2priv) +#define ec_key_parse_curve_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_key_parse_curve_name) #define EC_KEY_parse_curve_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_parse_curve_name) +#define ec_key_parse_parameters BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_key_parse_parameters) #define EC_KEY_parse_parameters BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_parse_parameters) +#define ec_key_parse_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_key_parse_private_key) #define EC_KEY_parse_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_parse_private_key) #define EC_KEY_priv2buf BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_priv2buf) #define EC_KEY_priv2oct BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_KEY_priv2oct) @@ -1465,6 +1509,7 @@ #define ED25519_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ED25519_verify) #define EDIPARTYNAME_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EDIPARTYNAME_free) #define EDIPARTYNAME_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EDIPARTYNAME_new) +#define ENGINE_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ENGINE_cleanup) #define ENGINE_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ENGINE_free) #define ENGINE_get_ECDSA_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ENGINE_get_ECDSA_method) #define ENGINE_get_RSA_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ENGINE_get_RSA_method) @@ -1477,6 +1522,7 @@ #define ERR_add_error_dataf BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ERR_add_error_dataf) #define ERR_clear_error BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ERR_clear_error) #define ERR_clear_system_error BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ERR_clear_system_error) +#define ERR_equals BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ERR_equals) #define ERR_error_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ERR_error_string) #define ERR_error_string_n BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ERR_error_string_n) #define ERR_free_strings BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ERR_free_strings) @@ -1703,6 +1749,7 @@ #define EVP_HPKE_KEY_zero BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEY_zero) #define EVP_hpke_p256_hkdf_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_hpke_p256_hkdf_sha256) #define EVP_hpke_x25519_hkdf_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_hpke_x25519_hkdf_sha256) +#define EVP_hpke_xwing BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_hpke_xwing) #define EVP_marshal_digest_algorithm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_marshal_digest_algorithm) #define EVP_marshal_digest_algorithm_no_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_marshal_digest_algorithm_no_params) #define EVP_marshal_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_marshal_private_key) @@ -1734,6 +1781,7 @@ #define EVP_md5 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_md5) #define EVP_md5_sha1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_md5_sha1) #define EVP_parse_digest_algorithm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_parse_digest_algorithm) +#define EVP_parse_digest_algorithm_nid BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_parse_digest_algorithm_nid) #define EVP_parse_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_parse_private_key) #define EVP_parse_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_parse_public_key) #define EVP_PBE_scrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PBE_scrypt) @@ -1786,9 +1834,21 @@ #define EVP_PKEY_derive BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_derive) #define EVP_PKEY_derive_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_derive_init) #define EVP_PKEY_derive_set_peer BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_derive_set_peer) +#define EVP_pkey_dsa BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_dsa) +#define EVP_pkey_ec_p224 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_ec_p224) +#define EVP_pkey_ec_p256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_ec_p256) +#define EVP_pkey_ec_p384 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_ec_p384) +#define EVP_pkey_ec_p521 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_ec_p521) +#define EVP_pkey_ed25519 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_ed25519) #define EVP_PKEY_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_encrypt) #define EVP_PKEY_encrypt_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_encrypt_init) #define EVP_PKEY_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_free) +#define EVP_PKEY_from_private_key_info BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_from_private_key_info) +#define EVP_PKEY_from_raw_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_from_raw_private_key) +#define EVP_PKEY_from_raw_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_from_raw_public_key) +#define EVP_PKEY_from_subject_public_key_info BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_from_subject_public_key_info) +#define EVP_PKEY_get_ec_curve_nid BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_get_ec_curve_nid) +#define EVP_PKEY_get_ec_point_conv_form BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_get_ec_point_conv_form) #define EVP_PKEY_get_raw_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_get_raw_private_key) #define EVP_PKEY_get_raw_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_get_raw_public_key) #define EVP_PKEY_get0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_get0) @@ -1814,8 +1874,10 @@ #define EVP_PKEY_print_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_print_params) #define EVP_PKEY_print_private BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_print_private) #define EVP_PKEY_print_public BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_print_public) -#define evp_pkey_set_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, evp_pkey_set_method) +#define EVP_pkey_rsa BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_rsa) +#define EVP_pkey_rsa_pss_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_rsa_pss_sha256) #define EVP_PKEY_set_type BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_set_type) +#define evp_pkey_set0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, evp_pkey_set0) #define EVP_PKEY_set1_DH BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_set1_DH) #define EVP_PKEY_set1_DSA BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_set1_DSA) #define EVP_PKEY_set1_EC_KEY BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_set1_EC_KEY) @@ -1830,6 +1892,7 @@ #define EVP_PKEY_verify_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_verify_init) #define EVP_PKEY_verify_recover BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_verify_recover) #define EVP_PKEY_verify_recover_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY_verify_recover_init) +#define EVP_pkey_x25519 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_pkey_x25519) #define EVP_PKEY2PKCS8 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_PKEY2PKCS8) #define EVP_rc2_40_cbc BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_rc2_40_cbc) #define EVP_rc2_cbc BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_rc2_cbc) @@ -1866,6 +1929,8 @@ #define FIPS_module_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_module_name) #define FIPS_query_algorithm_status BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_query_algorithm_status) #define FIPS_read_counter BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_read_counter) +#define FIPS_service_indicator_after_call BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_service_indicator_after_call) +#define FIPS_service_indicator_before_call BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_service_indicator_before_call) #define FIPS_version BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_version) #define gcm_ghash_avx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, gcm_ghash_avx) #define gcm_ghash_clmul BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, gcm_ghash_clmul) @@ -2041,7 +2106,6 @@ #define i2d_X509_AUX BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_AUX) #define i2d_X509_bio BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_bio) #define i2d_X509_CERT_AUX BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_CERT_AUX) -#define i2d_X509_CINF BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_CINF) #define i2d_X509_CRL BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_CRL) #define i2d_X509_CRL_bio BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_CRL_bio) #define i2d_X509_CRL_fp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_CRL_fp) @@ -2059,7 +2123,6 @@ #define i2d_X509_REVOKED BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_REVOKED) #define i2d_X509_SIG BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_SIG) #define i2d_X509_tbs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_tbs) -#define i2d_X509_VAL BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2d_X509_VAL) #define i2o_ECPublicKey BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2o_ECPublicKey) #define i2s_ASN1_ENUMERATED BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2s_ASN1_ENUMERATED) #define i2s_ASN1_INTEGER BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, i2s_ASN1_INTEGER) @@ -2123,6 +2186,17 @@ #define MD5_Update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MD5_Update) #define METHOD_ref BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, METHOD_ref) #define METHOD_unref BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, METHOD_unref) +#define MLDSA44_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_generate_key) +#define MLDSA44_marshal_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_marshal_public_key) +#define MLDSA44_parse_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_parse_public_key) +#define MLDSA44_prehash_finalize BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_prehash_finalize) +#define MLDSA44_prehash_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_prehash_init) +#define MLDSA44_prehash_update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_prehash_update) +#define MLDSA44_private_key_from_seed BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_private_key_from_seed) +#define MLDSA44_public_from_private BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_public_from_private) +#define MLDSA44_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_sign) +#define MLDSA44_sign_message_representative BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_sign_message_representative) +#define MLDSA44_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA44_verify) #define MLDSA65_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA65_generate_key) #define MLDSA65_marshal_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA65_marshal_public_key) #define MLDSA65_parse_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, MLDSA65_parse_public_key) @@ -2520,6 +2594,7 @@ #define rsa_invalidate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_invalidate_key) #define RSA_is_opaque BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_is_opaque) #define RSA_marshal_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_marshal_private_key) +#define rsa_marshal_pss_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_marshal_pss_params) #define RSA_marshal_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_marshal_public_key) #define RSA_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_new) #define RSA_new_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_new_method) @@ -2537,6 +2612,7 @@ #define RSA_padding_check_PKCS1_OAEP_mgf1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_padding_check_PKCS1_OAEP_mgf1) #define RSA_padding_check_PKCS1_type_1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_padding_check_PKCS1_type_1) #define RSA_parse_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_parse_private_key) +#define rsa_parse_pss_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_parse_pss_params) #define RSA_parse_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_parse_public_key) #define rsa_pkey_meth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_pkey_meth) #define RSA_print BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_print) @@ -2547,8 +2623,11 @@ #define rsa_private_transform BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_private_transform) #define rsa_private_transform_no_self_test BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_private_transform_no_self_test) #define RSA_PSS_PARAMS_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_PSS_PARAMS_free) +#define rsa_pss_params_get_md BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_pss_params_get_md) #define RSA_PSS_PARAMS_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_PSS_PARAMS_it) #define RSA_PSS_PARAMS_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_PSS_PARAMS_new) +#define rsa_pss_sha256_asn1_meth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_pss_sha256_asn1_meth) +#define rsa_pss_sha256_pkey_meth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, rsa_pss_sha256_pkey_meth) #define RSA_public_decrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_public_decrypt) #define RSA_public_encrypt BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_public_encrypt) #define RSA_public_key_from_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, RSA_public_key_from_bytes) @@ -2998,10 +3077,13 @@ #define X509_add1_ext_i2d BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_add1_ext_i2d) #define X509_add1_reject_object BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_add1_reject_object) #define X509_add1_trust_object BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_add1_trust_object) +#define x509_algor_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_algor_cleanup) #define X509_ALGOR_cmp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_cmp) +#define X509_ALGOR_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_copy) #define X509_ALGOR_dup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_dup) #define X509_ALGOR_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_free) #define X509_ALGOR_get0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_get0) +#define x509_algor_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_algor_init) #define X509_ALGOR_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_it) #define X509_ALGOR_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_new) #define X509_ALGOR_set_md BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_set_md) @@ -3038,9 +3120,6 @@ #define X509_check_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_check_private_key) #define X509_check_purpose BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_check_purpose) #define X509_check_trust BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_check_trust) -#define X509_CINF_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_free) -#define X509_CINF_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_it) -#define X509_CINF_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_new) #define X509_cmp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_cmp) #define X509_cmp_current_time BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_cmp_current_time) #define X509_cmp_time BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_cmp_time) @@ -3176,6 +3255,8 @@ #define X509_LOOKUP_load_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_LOOKUP_load_file) #define x509_marshal_algorithm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_marshal_algorithm) #define x509_marshal_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_marshal_name) +#define x509_marshal_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_marshal_public_key) +#define x509_marshal_tbs_cert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_marshal_tbs_cert) #define X509_NAME_add_entry BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_NAME_add_entry) #define X509_NAME_add_entry_by_NID BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_NAME_add_entry_by_NID) #define X509_NAME_add_entry_by_OBJ BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_NAME_add_entry_by_OBJ) @@ -3219,23 +3300,29 @@ #define X509_OBJECT_get_type BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_OBJECT_get_type) #define X509_OBJECT_get0_X509 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_OBJECT_get0_X509) #define X509_OBJECT_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_OBJECT_new) +#define x509_parse_algorithm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_parse_algorithm) #define X509_parse_from_buffer BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_parse_from_buffer) +#define x509_parse_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_parse_public_key) +#define X509_parse_with_algorithms BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_parse_with_algorithms) #define X509_policy_check BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_policy_check) #define X509_print BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_print) #define X509_print_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_print_ex) #define X509_print_ex_fp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_print_ex_fp) #define X509_print_fp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_print_fp) #define x509_print_rsa_pss_params BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_print_rsa_pss_params) +#define x509_pubkey_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_pubkey_cleanup) #define X509_pubkey_digest BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_pubkey_digest) #define X509_PUBKEY_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_free) #define X509_PUBKEY_get BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get) #define X509_PUBKEY_get0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get0) #define X509_PUBKEY_get0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get0_param) #define X509_PUBKEY_get0_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get0_public_key) +#define x509_pubkey_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_pubkey_init) #define X509_PUBKEY_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_it) #define X509_PUBKEY_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_new) #define X509_PUBKEY_set BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_set) #define X509_PUBKEY_set0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_set0_param) +#define x509_pubkey_set1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_pubkey_set1) #define X509_PURPOSE_get_by_sname BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PURPOSE_get_by_sname) #define X509_PURPOSE_get_id BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PURPOSE_get_id) #define X509_PURPOSE_get_trust BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PURPOSE_get_trust) @@ -3319,6 +3406,7 @@ #define X509_SIG_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_new) #define X509_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_sign) #define X509_sign_ctx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_sign_ctx) +#define x509_sign_to_bit_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_sign_to_bit_string) #define X509_signature_dump BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_signature_dump) #define X509_signature_print BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_signature_print) #define X509_STORE_add_cert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_add_cert) @@ -3383,9 +3471,6 @@ #define X509_time_adj_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_time_adj_ex) #define X509_trust_clear BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_trust_clear) #define X509_up_ref BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_up_ref) -#define X509_VAL_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_VAL_free) -#define X509_VAL_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_VAL_it) -#define X509_VAL_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_VAL_new) #define X509_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_verify) #define X509_verify_cert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_verify_cert) #define X509_verify_cert_error_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_verify_cert_error_string) @@ -3411,6 +3496,7 @@ #define X509_VERIFY_PARAM_set1_ip BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_VERIFY_PARAM_set1_ip) #define X509_VERIFY_PARAM_set1_ip_asc BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_VERIFY_PARAM_set1_ip_asc) #define X509_VERIFY_PARAM_set1_policies BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_VERIFY_PARAM_set1_policies) +#define x509_verify_signature BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509_verify_signature) #define x509v3_a2i_ipadd BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, x509v3_a2i_ipadd) #define X509v3_add_ext BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509v3_add_ext) #define X509V3_add_standard_extensions BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509V3_add_standard_extensions) @@ -4373,3 +4459,5 @@ #define lh_CRYPTO_BUFFER_call_doall_arg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, lh_CRYPTO_BUFFER_call_doall_arg) #define lh_CRYPTO_BUFFER_doall BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, lh_CRYPTO_BUFFER_doall) #define lh_CRYPTO_BUFFER_doall_arg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, lh_CRYPTO_BUFFER_doall_arg) +#define bignum_ctx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bignum_ctx) +#define evp_pkey_ctx_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, evp_pkey_ctx_st) diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h index 8fc7f8451..b23a01e7c 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_boringssl_prefix_symbols_asm.h @@ -170,8 +170,12 @@ #define _ASN1_item_sign_ctx BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_item_sign_ctx) #define _ASN1_item_unpack BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_item_unpack) #define _ASN1_item_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_item_verify) +#define _asn1_marshal_any BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_marshal_any) #define _asn1_marshal_bit_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_marshal_bit_string) #define _asn1_marshal_integer BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_marshal_integer) +#define _asn1_marshal_object BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_marshal_object) +#define _asn1_marshal_octet_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_marshal_octet_string) +#define _asn1_marshal_time BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_marshal_time) #define _ASN1_mbstring_copy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_mbstring_copy) #define _ASN1_mbstring_ncopy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_mbstring_ncopy) #define _ASN1_NULL_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_NULL_free) @@ -188,6 +192,20 @@ #define _ASN1_OCTET_STRING_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_OCTET_STRING_it) #define _ASN1_OCTET_STRING_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_OCTET_STRING_new) #define _ASN1_OCTET_STRING_set BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_OCTET_STRING_set) +#define _asn1_parse_any BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_any) +#define _asn1_parse_any_as_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_any_as_string) +#define _asn1_parse_bit_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_bit_string) +#define _asn1_parse_bit_string_with_bad_length BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_bit_string_with_bad_length) +#define _asn1_parse_bmp_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_bmp_string) +#define _asn1_parse_enumerated BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_enumerated) +#define _asn1_parse_generalized_time BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_generalized_time) +#define _asn1_parse_integer BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_integer) +#define _asn1_parse_object BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_object) +#define _asn1_parse_octet_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_octet_string) +#define _asn1_parse_time BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_time) +#define _asn1_parse_universal_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_universal_string) +#define _asn1_parse_utc_time BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_utc_time) +#define _asn1_parse_utf8_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_parse_utf8_string) #define _ASN1_primitive_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_primitive_free) #define _ASN1_PRINTABLESTRING_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_PRINTABLESTRING_free) #define _ASN1_PRINTABLESTRING_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_PRINTABLESTRING_it) @@ -198,6 +216,7 @@ #define _asn1_refcount_set_one BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_refcount_set_one) #define _ASN1_SEQUENCE_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_SEQUENCE_it) #define _asn1_set_choice_selector BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_set_choice_selector) +#define _asn1_string_cleanup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_string_cleanup) #define _ASN1_STRING_cmp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_cmp) #define _ASN1_STRING_copy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_copy) #define _ASN1_STRING_data BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_data) @@ -205,6 +224,7 @@ #define _ASN1_STRING_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_free) #define _ASN1_STRING_get_default_mask BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_get_default_mask) #define _ASN1_STRING_get0_data BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_get0_data) +#define _asn1_string_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_string_init) #define _ASN1_STRING_length BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_length) #define _ASN1_STRING_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_new) #define _ASN1_STRING_print BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ASN1_STRING_print) @@ -285,6 +305,26 @@ #define _bcm_as_approved_status BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bcm_as_approved_status) #define _bcm_as_not_approved_status BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bcm_as_not_approved_status) #define _BCM_fips_186_2_prf BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_fips_186_2_prf) +#define _BCM_mldsa44_check_key_fips BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_check_key_fips) +#define _BCM_mldsa44_generate_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_generate_key) +#define _BCM_mldsa44_generate_key_external_entropy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_generate_key_external_entropy) +#define _BCM_mldsa44_generate_key_external_entropy_fips BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_generate_key_external_entropy_fips) +#define _BCM_mldsa44_generate_key_fips BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_generate_key_fips) +#define _BCM_mldsa44_marshal_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_marshal_private_key) +#define _BCM_mldsa44_marshal_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_marshal_public_key) +#define _BCM_mldsa44_parse_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_parse_private_key) +#define _BCM_mldsa44_parse_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_parse_public_key) +#define _BCM_mldsa44_prehash_finalize BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_prehash_finalize) +#define _BCM_mldsa44_prehash_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_prehash_init) +#define _BCM_mldsa44_prehash_update BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_prehash_update) +#define _BCM_mldsa44_private_key_from_seed BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_private_key_from_seed) +#define _BCM_mldsa44_private_key_from_seed_fips BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_private_key_from_seed_fips) +#define _BCM_mldsa44_public_from_private BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_public_from_private) +#define _BCM_mldsa44_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_sign) +#define _BCM_mldsa44_sign_internal BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_sign_internal) +#define _BCM_mldsa44_sign_message_representative BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_sign_message_representative) +#define _BCM_mldsa44_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_verify) +#define _BCM_mldsa44_verify_internal BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa44_verify_internal) #define _BCM_mldsa65_check_key_fips BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa65_check_key_fips) #define _BCM_mldsa65_generate_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa65_generate_key) #define _BCM_mldsa65_generate_key_external_entropy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BCM_mldsa65_generate_key_external_entropy) @@ -635,9 +675,9 @@ #define _bn_mul_comba4 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_comba4) #define _bn_mul_comba8 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_comba8) #define _bn_mul_consttime BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_consttime) -#define _bn_mul_mont BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_mont) #define _bn_mul_mont_gather5_nohw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_mont_gather5_nohw) #define _bn_mul_mont_nohw BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_mont_nohw) +#define _bn_mul_mont_words BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_mont_words) #define _bn_mul_small BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_small) #define _BN_mul_word BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, BN_mul_word) #define _bn_mul_words BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bn_mul_words) @@ -885,6 +925,7 @@ #define _CMS_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CMS_sign) #define _CONF_modules_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CONF_modules_free) #define _CONF_modules_load_file BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CONF_modules_load_file) +#define _CONF_modules_unload BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CONF_modules_unload) #define _CONF_parse_list BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CONF_parse_list) #define _CONF_VALUE_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CONF_VALUE_new) #define _CRL_DIST_POINTS_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CRL_DIST_POINTS_free) @@ -1019,7 +1060,9 @@ #define _CTR_DRBG_generate BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CTR_DRBG_generate) #define _CTR_DRBG_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CTR_DRBG_init) #define _CTR_DRBG_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CTR_DRBG_new) +#define _CTR_DRBG_new_df BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CTR_DRBG_new_df) #define _CTR_DRBG_reseed BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CTR_DRBG_reseed) +#define _CTR_DRBG_reseed_ex BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CTR_DRBG_reseed_ex) #define _d2i_ASN1_BIT_STRING BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_ASN1_BIT_STRING) #define _d2i_ASN1_BMPSTRING BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_ASN1_BMPSTRING) #define _d2i_ASN1_BOOLEAN BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_ASN1_BOOLEAN) @@ -1110,7 +1153,6 @@ #define _d2i_X509_AUX BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_AUX) #define _d2i_X509_bio BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_bio) #define _d2i_X509_CERT_AUX BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_CERT_AUX) -#define _d2i_X509_CINF BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_CINF) #define _d2i_X509_CRL BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_CRL) #define _d2i_X509_CRL_bio BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_CRL_bio) #define _d2i_X509_CRL_fp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_CRL_fp) @@ -1126,7 +1168,6 @@ #define _d2i_X509_REQ_INFO BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_REQ_INFO) #define _d2i_X509_REVOKED BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_REVOKED) #define _d2i_X509_SIG BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_SIG) -#define _d2i_X509_VAL BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, d2i_X509_VAL) #define _DES_decrypt3 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DES_decrypt3) #define _DES_ecb_encrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DES_ecb_encrypt) #define _DES_ecb_encrypt_ex BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DES_ecb_encrypt_ex) @@ -1334,8 +1375,11 @@ #define _EC_KEY_new_method BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_new_method) #define _EC_KEY_oct2key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_oct2key) #define _EC_KEY_oct2priv BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_oct2priv) +#define _ec_key_parse_curve_name BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ec_key_parse_curve_name) #define _EC_KEY_parse_curve_name BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_parse_curve_name) +#define _ec_key_parse_parameters BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ec_key_parse_parameters) #define _EC_KEY_parse_parameters BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_parse_parameters) +#define _ec_key_parse_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ec_key_parse_private_key) #define _EC_KEY_parse_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_parse_private_key) #define _EC_KEY_priv2buf BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_priv2buf) #define _EC_KEY_priv2oct BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EC_KEY_priv2oct) @@ -1470,6 +1514,7 @@ #define _ED25519_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ED25519_verify) #define _EDIPARTYNAME_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EDIPARTYNAME_free) #define _EDIPARTYNAME_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EDIPARTYNAME_new) +#define _ENGINE_cleanup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ENGINE_cleanup) #define _ENGINE_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ENGINE_free) #define _ENGINE_get_ECDSA_method BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ENGINE_get_ECDSA_method) #define _ENGINE_get_RSA_method BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ENGINE_get_RSA_method) @@ -1482,6 +1527,7 @@ #define _ERR_add_error_dataf BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ERR_add_error_dataf) #define _ERR_clear_error BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ERR_clear_error) #define _ERR_clear_system_error BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ERR_clear_system_error) +#define _ERR_equals BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ERR_equals) #define _ERR_error_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ERR_error_string) #define _ERR_error_string_n BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ERR_error_string_n) #define _ERR_free_strings BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, ERR_free_strings) @@ -1708,6 +1754,7 @@ #define _EVP_HPKE_KEY_zero BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEY_zero) #define _EVP_hpke_p256_hkdf_sha256 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_hpke_p256_hkdf_sha256) #define _EVP_hpke_x25519_hkdf_sha256 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_hpke_x25519_hkdf_sha256) +#define _EVP_hpke_xwing BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_hpke_xwing) #define _EVP_marshal_digest_algorithm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_marshal_digest_algorithm) #define _EVP_marshal_digest_algorithm_no_params BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_marshal_digest_algorithm_no_params) #define _EVP_marshal_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_marshal_private_key) @@ -1739,6 +1786,7 @@ #define _EVP_md5 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_md5) #define _EVP_md5_sha1 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_md5_sha1) #define _EVP_parse_digest_algorithm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_parse_digest_algorithm) +#define _EVP_parse_digest_algorithm_nid BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_parse_digest_algorithm_nid) #define _EVP_parse_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_parse_private_key) #define _EVP_parse_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_parse_public_key) #define _EVP_PBE_scrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PBE_scrypt) @@ -1791,9 +1839,21 @@ #define _EVP_PKEY_derive BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_derive) #define _EVP_PKEY_derive_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_derive_init) #define _EVP_PKEY_derive_set_peer BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_derive_set_peer) +#define _EVP_pkey_dsa BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_dsa) +#define _EVP_pkey_ec_p224 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_ec_p224) +#define _EVP_pkey_ec_p256 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_ec_p256) +#define _EVP_pkey_ec_p384 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_ec_p384) +#define _EVP_pkey_ec_p521 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_ec_p521) +#define _EVP_pkey_ed25519 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_ed25519) #define _EVP_PKEY_encrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_encrypt) #define _EVP_PKEY_encrypt_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_encrypt_init) #define _EVP_PKEY_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_free) +#define _EVP_PKEY_from_private_key_info BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_from_private_key_info) +#define _EVP_PKEY_from_raw_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_from_raw_private_key) +#define _EVP_PKEY_from_raw_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_from_raw_public_key) +#define _EVP_PKEY_from_subject_public_key_info BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_from_subject_public_key_info) +#define _EVP_PKEY_get_ec_curve_nid BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_get_ec_curve_nid) +#define _EVP_PKEY_get_ec_point_conv_form BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_get_ec_point_conv_form) #define _EVP_PKEY_get_raw_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_get_raw_private_key) #define _EVP_PKEY_get_raw_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_get_raw_public_key) #define _EVP_PKEY_get0 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_get0) @@ -1819,8 +1879,10 @@ #define _EVP_PKEY_print_params BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_print_params) #define _EVP_PKEY_print_private BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_print_private) #define _EVP_PKEY_print_public BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_print_public) -#define _evp_pkey_set_method BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, evp_pkey_set_method) +#define _EVP_pkey_rsa BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_rsa) +#define _EVP_pkey_rsa_pss_sha256 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_rsa_pss_sha256) #define _EVP_PKEY_set_type BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_set_type) +#define _evp_pkey_set0 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, evp_pkey_set0) #define _EVP_PKEY_set1_DH BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_set1_DH) #define _EVP_PKEY_set1_DSA BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_set1_DSA) #define _EVP_PKEY_set1_EC_KEY BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_set1_EC_KEY) @@ -1835,6 +1897,7 @@ #define _EVP_PKEY_verify_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_verify_init) #define _EVP_PKEY_verify_recover BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_verify_recover) #define _EVP_PKEY_verify_recover_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY_verify_recover_init) +#define _EVP_pkey_x25519 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_pkey_x25519) #define _EVP_PKEY2PKCS8 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_PKEY2PKCS8) #define _EVP_rc2_40_cbc BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_rc2_40_cbc) #define _EVP_rc2_cbc BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_rc2_cbc) @@ -1871,6 +1934,8 @@ #define _FIPS_module_name BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_module_name) #define _FIPS_query_algorithm_status BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_query_algorithm_status) #define _FIPS_read_counter BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_read_counter) +#define _FIPS_service_indicator_after_call BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_service_indicator_after_call) +#define _FIPS_service_indicator_before_call BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_service_indicator_before_call) #define _FIPS_version BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_version) #define _gcm_ghash_avx BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, gcm_ghash_avx) #define _gcm_ghash_clmul BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, gcm_ghash_clmul) @@ -2046,7 +2111,6 @@ #define _i2d_X509_AUX BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_AUX) #define _i2d_X509_bio BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_bio) #define _i2d_X509_CERT_AUX BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_CERT_AUX) -#define _i2d_X509_CINF BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_CINF) #define _i2d_X509_CRL BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_CRL) #define _i2d_X509_CRL_bio BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_CRL_bio) #define _i2d_X509_CRL_fp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_CRL_fp) @@ -2064,7 +2128,6 @@ #define _i2d_X509_REVOKED BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_REVOKED) #define _i2d_X509_SIG BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_SIG) #define _i2d_X509_tbs BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_tbs) -#define _i2d_X509_VAL BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2d_X509_VAL) #define _i2o_ECPublicKey BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2o_ECPublicKey) #define _i2s_ASN1_ENUMERATED BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2s_ASN1_ENUMERATED) #define _i2s_ASN1_INTEGER BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, i2s_ASN1_INTEGER) @@ -2128,6 +2191,17 @@ #define _MD5_Update BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MD5_Update) #define _METHOD_ref BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, METHOD_ref) #define _METHOD_unref BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, METHOD_unref) +#define _MLDSA44_generate_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_generate_key) +#define _MLDSA44_marshal_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_marshal_public_key) +#define _MLDSA44_parse_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_parse_public_key) +#define _MLDSA44_prehash_finalize BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_prehash_finalize) +#define _MLDSA44_prehash_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_prehash_init) +#define _MLDSA44_prehash_update BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_prehash_update) +#define _MLDSA44_private_key_from_seed BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_private_key_from_seed) +#define _MLDSA44_public_from_private BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_public_from_private) +#define _MLDSA44_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_sign) +#define _MLDSA44_sign_message_representative BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_sign_message_representative) +#define _MLDSA44_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA44_verify) #define _MLDSA65_generate_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA65_generate_key) #define _MLDSA65_marshal_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA65_marshal_public_key) #define _MLDSA65_parse_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, MLDSA65_parse_public_key) @@ -2525,6 +2599,7 @@ #define _rsa_invalidate_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_invalidate_key) #define _RSA_is_opaque BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_is_opaque) #define _RSA_marshal_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_marshal_private_key) +#define _rsa_marshal_pss_params BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_marshal_pss_params) #define _RSA_marshal_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_marshal_public_key) #define _RSA_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_new) #define _RSA_new_method BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_new_method) @@ -2542,6 +2617,7 @@ #define _RSA_padding_check_PKCS1_OAEP_mgf1 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_padding_check_PKCS1_OAEP_mgf1) #define _RSA_padding_check_PKCS1_type_1 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_padding_check_PKCS1_type_1) #define _RSA_parse_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_parse_private_key) +#define _rsa_parse_pss_params BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_parse_pss_params) #define _RSA_parse_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_parse_public_key) #define _rsa_pkey_meth BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_pkey_meth) #define _RSA_print BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_print) @@ -2552,8 +2628,11 @@ #define _rsa_private_transform BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_private_transform) #define _rsa_private_transform_no_self_test BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_private_transform_no_self_test) #define _RSA_PSS_PARAMS_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_PSS_PARAMS_free) +#define _rsa_pss_params_get_md BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_pss_params_get_md) #define _RSA_PSS_PARAMS_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_PSS_PARAMS_it) #define _RSA_PSS_PARAMS_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_PSS_PARAMS_new) +#define _rsa_pss_sha256_asn1_meth BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_pss_sha256_asn1_meth) +#define _rsa_pss_sha256_pkey_meth BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, rsa_pss_sha256_pkey_meth) #define _RSA_public_decrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_public_decrypt) #define _RSA_public_encrypt BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_public_encrypt) #define _RSA_public_key_from_bytes BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, RSA_public_key_from_bytes) @@ -3003,10 +3082,13 @@ #define _X509_add1_ext_i2d BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_add1_ext_i2d) #define _X509_add1_reject_object BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_add1_reject_object) #define _X509_add1_trust_object BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_add1_trust_object) +#define _x509_algor_cleanup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_algor_cleanup) #define _X509_ALGOR_cmp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_cmp) +#define _X509_ALGOR_copy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_copy) #define _X509_ALGOR_dup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_dup) #define _X509_ALGOR_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_free) #define _X509_ALGOR_get0 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_get0) +#define _x509_algor_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_algor_init) #define _X509_ALGOR_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_it) #define _X509_ALGOR_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_new) #define _X509_ALGOR_set_md BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_set_md) @@ -3043,9 +3125,6 @@ #define _X509_check_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_check_private_key) #define _X509_check_purpose BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_check_purpose) #define _X509_check_trust BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_check_trust) -#define _X509_CINF_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_CINF_free) -#define _X509_CINF_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_CINF_it) -#define _X509_CINF_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_CINF_new) #define _X509_cmp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_cmp) #define _X509_cmp_current_time BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_cmp_current_time) #define _X509_cmp_time BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_cmp_time) @@ -3181,6 +3260,8 @@ #define _X509_LOOKUP_load_file BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_LOOKUP_load_file) #define _x509_marshal_algorithm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_marshal_algorithm) #define _x509_marshal_name BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_marshal_name) +#define _x509_marshal_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_marshal_public_key) +#define _x509_marshal_tbs_cert BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_marshal_tbs_cert) #define _X509_NAME_add_entry BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_NAME_add_entry) #define _X509_NAME_add_entry_by_NID BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_NAME_add_entry_by_NID) #define _X509_NAME_add_entry_by_OBJ BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_NAME_add_entry_by_OBJ) @@ -3224,23 +3305,29 @@ #define _X509_OBJECT_get_type BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_OBJECT_get_type) #define _X509_OBJECT_get0_X509 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_OBJECT_get0_X509) #define _X509_OBJECT_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_OBJECT_new) +#define _x509_parse_algorithm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_parse_algorithm) #define _X509_parse_from_buffer BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_parse_from_buffer) +#define _x509_parse_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_parse_public_key) +#define _X509_parse_with_algorithms BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_parse_with_algorithms) #define _X509_policy_check BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_policy_check) #define _X509_print BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_print) #define _X509_print_ex BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_print_ex) #define _X509_print_ex_fp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_print_ex_fp) #define _X509_print_fp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_print_fp) #define _x509_print_rsa_pss_params BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_print_rsa_pss_params) +#define _x509_pubkey_cleanup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_pubkey_cleanup) #define _X509_pubkey_digest BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_pubkey_digest) #define _X509_PUBKEY_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_free) #define _X509_PUBKEY_get BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_get) #define _X509_PUBKEY_get0 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_get0) #define _X509_PUBKEY_get0_param BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_get0_param) #define _X509_PUBKEY_get0_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_get0_public_key) +#define _x509_pubkey_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_pubkey_init) #define _X509_PUBKEY_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_it) #define _X509_PUBKEY_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_new) #define _X509_PUBKEY_set BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_set) #define _X509_PUBKEY_set0_param BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_set0_param) +#define _x509_pubkey_set1 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_pubkey_set1) #define _X509_PURPOSE_get_by_sname BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PURPOSE_get_by_sname) #define _X509_PURPOSE_get_id BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PURPOSE_get_id) #define _X509_PURPOSE_get_trust BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PURPOSE_get_trust) @@ -3324,6 +3411,7 @@ #define _X509_SIG_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_SIG_new) #define _X509_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_sign) #define _X509_sign_ctx BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_sign_ctx) +#define _x509_sign_to_bit_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_sign_to_bit_string) #define _X509_signature_dump BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_signature_dump) #define _X509_signature_print BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_signature_print) #define _X509_STORE_add_cert BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_STORE_add_cert) @@ -3388,9 +3476,6 @@ #define _X509_time_adj_ex BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_time_adj_ex) #define _X509_trust_clear BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_trust_clear) #define _X509_up_ref BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_up_ref) -#define _X509_VAL_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_VAL_free) -#define _X509_VAL_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_VAL_it) -#define _X509_VAL_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_VAL_new) #define _X509_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_verify) #define _X509_verify_cert BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_verify_cert) #define _X509_verify_cert_error_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_verify_cert_error_string) @@ -3416,6 +3501,7 @@ #define _X509_VERIFY_PARAM_set1_ip BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_VERIFY_PARAM_set1_ip) #define _X509_VERIFY_PARAM_set1_ip_asc BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_VERIFY_PARAM_set1_ip_asc) #define _X509_VERIFY_PARAM_set1_policies BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_VERIFY_PARAM_set1_policies) +#define _x509_verify_signature BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509_verify_signature) #define _x509v3_a2i_ipadd BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, x509v3_a2i_ipadd) #define _X509v3_add_ext BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509v3_add_ext) #define _X509V3_add_standard_extensions BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509V3_add_standard_extensions) diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_conf.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_conf.h index 3be4e1de6..c5f0af94f 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_conf.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_conf.h @@ -96,6 +96,9 @@ OPENSSL_EXPORT int CONF_modules_load_file(const char *filename, const char *appname, unsigned long flags); +// CONF_modules_unload does nothing. +OPENSSL_EXPORT void CONF_modules_unload(int all); + // CONF_modules_free does nothing. OPENSSL_EXPORT void CONF_modules_free(void); diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_crypto.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_crypto.h index 81a8a8a3c..f7931bd35 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_crypto.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_crypto.h @@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_CRYPTO_H #define OPENSSL_HEADER_CRYPTO_H -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export #include "CCryptoBoringSSL_sha.h" // Upstream OpenSSL defines |OPENSSL_malloc|, etc., in crypto.h rather than @@ -162,6 +162,9 @@ OPENSSL_EXPORT void ENGINE_load_builtin_engines(void); // ENGINE_register_all_complete returns one. OPENSSL_EXPORT int ENGINE_register_all_complete(void); +// ENGINE_cleanup does nothing. +OPENSSL_EXPORT void ENGINE_cleanup(void); + // OPENSSL_load_builtin_modules does nothing. OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void); @@ -205,8 +208,7 @@ OPENSSL_EXPORT const uint8_t *FIPS_module_hash(void); // FIPS_version returns the version of the FIPS module, or zero if the build // isn't exactly at a verified version. The version, expressed in base 10, will -// be a date in the form yyyymmddXX where XX is often "00", but can be -// incremented if multiple versions are defined on a single day. +// be a date in the form yyyymmdd. // // (This format exceeds a |uint32_t| in the year 4294.) OPENSSL_EXPORT uint32_t FIPS_version(void); diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ctrdrbg.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ctrdrbg.h index fb3336d69..8aa56a983 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ctrdrbg.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ctrdrbg.h @@ -15,7 +15,7 @@ #ifndef OPENSSL_HEADER_CTRDRBG_H #define OPENSSL_HEADER_CTRDRBG_H -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -29,33 +29,67 @@ extern "C" { // // CTR_DRBG_STATE contains the state of a FIPS AES-CTR-based pseudo-random // number generator. If BoringSSL was built in FIPS mode then this is a FIPS -// Approved algorithm. +// Approved algorithm. BoringSSL supports CTR-DRBG both with, and without, a +// derivation function. -// CTR_DRBG_ENTROPY_LEN is the number of bytes of input entropy. See SP -// 800-90Ar1, table 3. +// CTR_DRBG_MIN_ENTROPY_LEN is the minimum number of bytes of input entropy +// when using a derivation function. See SP 800-90Ar1, table 3. +#define CTR_DRBG_MIN_ENTROPY_LEN 32 + +// CTR_DRBG_MAX_ENTROPY_LEN is the maximum number of bytes of input entropy +// when using a derivation function. This is an implementation limitation. +#define CTR_DRBG_MAX_ENTROPY_LEN 64 + +// CTR_DRBG_ENTROPY_LEN is a fixed amount of entropy required when not using a +// derivation function. #define CTR_DRBG_ENTROPY_LEN 48 +// The length of a seed, when using a derivation function. See SP 800-90Ar1, +// table 3. +#define CTR_DRBG_SEED_LEN (32 + CTR_DRBG_NONCE_LEN) + +// CTR_DRBG_NONCE_LEN is the number of bytes of input nonce. This only applies +// when using a derivation function. +#define CTR_DRBG_NONCE_LEN 16 + // CTR_DRBG_MAX_GENERATE_LENGTH is the maximum number of bytes that can be // generated in a single call to |CTR_DRBG_generate|. #define CTR_DRBG_MAX_GENERATE_LENGTH 65536 // CTR_DRBG_new returns an initialized |CTR_DRBG_STATE|, or NULL if either -// allocation failed or if |personalization_len| is invalid. +// allocation failed or if |personalization_len| is invalid. This DRBG will not +// use a derivation function. OPENSSL_EXPORT CTR_DRBG_STATE *CTR_DRBG_new( const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], const uint8_t *personalization, size_t personalization_len); +// CTR_DRBG_new_df returns an initialized |CTR_DRBG_STATE|, or NULL if either +// allocation failed or if an argument is invalid. This DRBG will use a +// derivation function. +OPENSSL_EXPORT CTR_DRBG_STATE *CTR_DRBG_new_df( + const uint8_t *entropy, size_t entropy_len, + const uint8_t nonce[CTR_DRBG_NONCE_LEN], const uint8_t *personalization, + size_t personalization_len); + // CTR_DRBG_free frees |state| if non-NULL, or else does nothing. -OPENSSL_EXPORT void CTR_DRBG_free(CTR_DRBG_STATE* state); +OPENSSL_EXPORT void CTR_DRBG_free(CTR_DRBG_STATE *state); // CTR_DRBG_reseed reseeds |drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of entropy -// in |entropy| and, optionally, up to |CTR_DRBG_ENTROPY_LEN| bytes of +// in |entropy| and, optionally, up to |CTR_DRBG_SEED_LEN| bytes of // additional data. It returns one on success or zero on error. OPENSSL_EXPORT int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg, const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], const uint8_t *additional_data, size_t additional_data_len); +// CTR_DRBG_reseed_ex acts like `CTR_DRBG_reseed` but with variable-length +// entropy input, up to |CTR_DRBG_MAX_ENTROPY_LEN|. +OPENSSL_EXPORT int CTR_DRBG_reseed_ex(CTR_DRBG_STATE *drbg, + const uint8_t *entropy, + size_t entropy_len, + const uint8_t *additional_data, + size_t additional_data_len); + // CTR_DRBG_generate processes to up |CTR_DRBG_ENTROPY_LEN| bytes of additional // data (if any) and then writes |out_len| random bytes to |out|, where // |out_len| <= |CTR_DRBG_MAX_GENERATE_LENGTH|. It returns one on success or diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dh.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dh.h index f7db3d8e9..ce6057ed6 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dh.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dh.h @@ -54,7 +54,7 @@ OPENSSL_EXPORT int DH_up_ref(DH *dh); // OPENSSL_DH_MAX_MODULUS_BITS is the maximum supported Diffie-Hellman group // modulus, in bits. -#define OPENSSL_DH_MAX_MODULUS_BITS 10000 +#define OPENSSL_DH_MAX_MODULUS_BITS 8192 // DH_bits returns the size of |dh|'s group modulus, in bits. OPENSSL_EXPORT unsigned DH_bits(const DH *dh); @@ -111,32 +111,38 @@ OPENSSL_EXPORT DH *DH_get_rfc7919_2048(void); // BN_get_rfc3526_prime_1536 sets |*ret| to the 1536-bit MODP group from RFC // 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated -// and returned. It returns NULL on allocation failure. +// and returned. It returns NULL on allocation failure. The generator for this +// group is 2. OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *ret); // BN_get_rfc3526_prime_2048 sets |*ret| to the 2048-bit MODP group from RFC // 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated -// and returned. It returns NULL on allocation failure. +// and returned. It returns NULL on allocation failure. The generator for this +// group is 2. OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *ret); // BN_get_rfc3526_prime_3072 sets |*ret| to the 3072-bit MODP group from RFC // 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated -// and returned. It returns NULL on allocation failure. +// and returned. It returns NULL on allocation failure. The generator for this +// group is 2. OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *ret); // BN_get_rfc3526_prime_4096 sets |*ret| to the 4096-bit MODP group from RFC // 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated -// and returned. It returns NULL on allocation failure. +// and returned. It returns NULL on allocation failure. The generator for this +// group is 2. OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *ret); // BN_get_rfc3526_prime_6144 sets |*ret| to the 6144-bit MODP group from RFC // 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated -// and returned. It returns NULL on allocation failure. +// and returned. It returns NULL on allocation failure. The generator for this +// group is 2. OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *ret); // BN_get_rfc3526_prime_8192 sets |*ret| to the 8192-bit MODP group from RFC // 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated -// and returned. It returns NULL on allocation failure. +// and returned. It returns NULL on allocation failure. The generator for this +// group is 2. OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *ret); diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_digest.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_digest.h index 7fb79e1a6..179f92a7d 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_digest.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_digest.h @@ -213,6 +213,11 @@ OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx); // returns the digest function or NULL on error. OPENSSL_EXPORT const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs); +// EVP_parse_digest_algorithm_nid behaves like |EVP_parse_digest_algorithm| +// except it returns |NID_undef| on error and some other value on success. This +// may be used to avoid depending on every digest algorithm in the library. +OPENSSL_EXPORT int EVP_parse_digest_algorithm_nid(CBS *cbs); + // EVP_marshal_digest_algorithm marshals |md| as an AlgorithmIdentifier // structure and appends the result to |cbb|. It returns one on success and zero // on error. It sets the parameters field to NULL. Use @@ -283,17 +288,27 @@ OPENSSL_EXPORT void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); OPENSSL_EXPORT int EVP_MD_nid(const EVP_MD *md); +// Internal constants and structures (hidden). + struct evp_md_pctx_ops; +// EVP_MAX_MD_DATA_SIZE is a private constant which specifies the size of the +// largest digest state. SHA-512 and BLAKE2b are joint-largest. Consuming code +// only uses this via the `EVP_MD_CTX` type. +#define EVP_MAX_MD_DATA_SIZE 208 + // env_md_ctx_st is typoed ("evp" -> "env"), but the typo comes from OpenSSL // and some consumers forward-declare these structures so we're leaving it // alone. struct env_md_ctx_st { + // md_data contains the hash-specific context. + union { + uint8_t md_data[EVP_MAX_MD_DATA_SIZE]; + uint64_t alignment; + }; + // digest is the underlying digest function, or NULL if not set. const EVP_MD *digest; - // md_data points to a block of memory that contains the hash-specific - // context. - void *md_data; // pctx is an opaque (at this layer) pointer to additional context that // EVP_PKEY functions may store in this object. diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dsa.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dsa.h index e7e0e3b7a..07c716975 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dsa.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_dsa.h @@ -56,7 +56,7 @@ OPENSSL_EXPORT int DSA_up_ref(DSA *dsa); // OPENSSL_DSA_MAX_MODULUS_BITS is the maximum supported DSA group modulus, in // bits. -#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +#define OPENSSL_DSA_MAX_MODULUS_BITS 8192 // DSA_bits returns the size of |dsa|'s group modulus, in bits. OPENSSL_EXPORT unsigned DSA_bits(const DSA *dsa); diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec.h index e1f997101..e43aefd97 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec.h @@ -107,8 +107,8 @@ OPENSSL_EXPORT const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group); // EC_GROUP_order_bits returns the number of bits of the order of |group|. OPENSSL_EXPORT int EC_GROUP_order_bits(const EC_GROUP *group); -// EC_GROUP_get_cofactor sets |*cofactor| to the cofactor of |group| using -// |ctx|, if it's not NULL. It returns one on success and zero otherwise. +// EC_GROUP_get_cofactor sets |*cofactor| to the cofactor of |group|. It returns +// one on success and zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx); @@ -116,7 +116,7 @@ OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group, // |*out_p| to the order of the coordinate field and |*out_a| and |*out_b| to // the parameters of the curve when expressed as y² = x³ + ax + b. Any of the // output parameters can be NULL. It returns one on success and zero on -// error. +// error. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a, BIGNUM *out_b, BN_CTX *ctx); @@ -169,12 +169,12 @@ OPENSSL_EXPORT int EC_POINT_is_at_infinity(const EC_GROUP *group, // EC_POINT_is_on_curve returns one if |point| is an element of |group| and // and zero otherwise or when an error occurs. This is different from OpenSSL, -// which returns -1 on error. If |ctx| is non-NULL, it may be used. +// which returns -1 on error. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx); // EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero if -// not equal and -1 on error. If |ctx| is not NULL, it may be used. +// not equal and -1 on error. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx); @@ -182,8 +182,8 @@ OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, // Point conversion. // EC_POINT_get_affine_coordinates_GFp sets |x| and |y| to the affine value of -// |point| using |ctx|, if it's not NULL. It returns one on success and zero -// otherwise. +// |point|. It returns one on success and zero otherwise. |ctx| is ignored and +// may be NULL. // // Either |x| or |y| may be NULL to skip computing that coordinate. This is // slightly faster in the common case where only the x-coordinate is needed. @@ -200,9 +200,8 @@ OPENSSL_EXPORT int EC_POINT_get_affine_coordinates(const EC_GROUP *group, BN_CTX *ctx); // EC_POINT_set_affine_coordinates_GFp sets the value of |point| to be -// (|x|, |y|). The |ctx| argument may be used if not NULL. It returns one -// on success or zero on error. It's considered an error if the point is not on -// the curve. +// (|x|, |y|). |ctx| is ignored and may be NULL. It returns one on success or +// zero on error. It's considered an error if the point is not on the curve. // // Note that the corresponding function in OpenSSL versions prior to 1.0.2s does // not check if the point is on the curve. This is a security-critical check, so @@ -226,7 +225,7 @@ OPENSSL_EXPORT int EC_POINT_set_affine_coordinates(const EC_GROUP *group, // EC_POINT_point2oct serialises |point| into the X9.62 form given by |form| // into, at most, |max_out| bytes at |buf|. It returns the number of bytes // written or zero on error if |buf| is non-NULL, else the number of bytes -// needed. The |ctx| argument may be used if not NULL. +// needed. |ctx| is ignored and may be NULL. OPENSSL_EXPORT size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, @@ -236,30 +235,31 @@ OPENSSL_EXPORT size_t EC_POINT_point2oct(const EC_GROUP *group, // EC_POINT_point2buf serialises |point| into the X9.62 form given by |form| to // a newly-allocated buffer and sets |*out_buf| to point to it. It returns the // length of the result on success or zero on error. The caller must release -// |*out_buf| with |OPENSSL_free| when done. +// |*out_buf| with |OPENSSL_free| when done. |ctx| is ignored and may be NULL. OPENSSL_EXPORT size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, uint8_t **out_buf, BN_CTX *ctx); // EC_POINT_point2cbb behaves like |EC_POINT_point2oct| but appends the -// serialised point to |cbb|. It returns one on success and zero on error. +// serialised point to |cbb|. It returns one on success and zero on error. |ctx| +// is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, BN_CTX *ctx); // EC_POINT_oct2point sets |point| from |len| bytes of X9.62 format -// serialisation in |buf|. It returns one on success and zero on error. The -// |ctx| argument may be used if not NULL. It's considered an error if |buf| -// does not represent a point on the curve. +// serialisation in |buf|. It returns one on success and zero on error. |ctx| +// may be NULL. It's considered an error if |buf| does not represent a point on +// the curve. OPENSSL_EXPORT int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, const uint8_t *buf, size_t len, BN_CTX *ctx); // EC_POINT_set_compressed_coordinates_GFp sets |point| to equal the point with // the given |x| coordinate and the y coordinate specified by |y_bit| (see -// X9.62). It returns one on success and zero otherwise. +// X9.62). It returns one on success and zero otherwise. |ctx| may be NULL. OPENSSL_EXPORT int EC_POINT_set_compressed_coordinates_GFp( const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit, BN_CTX *ctx); @@ -268,23 +268,23 @@ OPENSSL_EXPORT int EC_POINT_set_compressed_coordinates_GFp( // Group operations. // EC_POINT_add sets |r| equal to |a| plus |b|. It returns one on success and -// zero otherwise. If |ctx| is not NULL, it may be used. +// zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx); // EC_POINT_dbl sets |r| equal to |a| plus |a|. It returns one on success and -// zero otherwise. If |ctx| is not NULL, it may be used. +// zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx); // EC_POINT_invert sets |a| equal to minus |a|. It returns one on success and -// zero otherwise. If |ctx| is not NULL, it may be used. +// zero otherwise. |ctx| is ignored and may be NULL. OPENSSL_EXPORT int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx); // EC_POINT_mul sets r = generator*n + q*m. It returns one on success and zero -// otherwise. If |ctx| is not NULL, it may be used. +// otherwise. |ctx| may be NULL. OPENSSL_EXPORT int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); @@ -368,8 +368,8 @@ OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group, const BIGNUM *cofactor); // EC_GROUP_get_order sets |*order| to the order of |group|, if it's not -// NULL. It returns one on success and zero otherwise. |ctx| is ignored. Use -// |EC_GROUP_get0_order| instead. +// NULL. It returns one on success and zero otherwise. |ctx| is ignored and may +// be NULL. Use |EC_GROUP_get0_order| instead. OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec_key.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec_key.h index 8dc963143..45a1c2216 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec_key.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_ec_key.h @@ -130,12 +130,12 @@ OPENSSL_EXPORT int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, // EC_KEY_oct2key decodes |len| bytes from |in| as an EC public key in X9.62 // form. |key| must already have a group configured. On success, it sets the // public key in |key| to the result and returns one. Otherwise, it returns -// zero. +// zero. |ctx| may be NULL. OPENSSL_EXPORT int EC_KEY_oct2key(EC_KEY *key, const uint8_t *in, size_t len, BN_CTX *ctx); // EC_KEY_key2buf behaves like |EC_POINT_point2buf|, except it encodes the -// public key in |key|. +// public key in |key|. |ctx| is ignored and may be NULL. OPENSSL_EXPORT size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, uint8_t **out_buf, BN_CTX *ctx); diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_err.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_err.h index b58ba1c4e..26d802b93 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_err.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_err.h @@ -80,6 +80,13 @@ OPENSSL_INLINE int ERR_GET_REASON(uint32_t packed_error) { return (int)(packed_error & 0xfff); } +// ERR_equals returns one if |packed_error|'s library and reason code are |lib| +// and |reason|, respectively, and zero otherwise. +OPENSSL_INLINE int ERR_equals(uint32_t packed_error, int lib, int reason) { + return ERR_GET_LIB(packed_error) == lib && + ERR_GET_REASON(packed_error) == reason; +} + // ERR_get_error gets the packed error code for the least recent error and // removes that error from the queue. If there are no errors in the queue then // it returns zero. diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp.h index 115185a64..48ebc93dd 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp.h @@ -21,8 +21,6 @@ // OpenSSL included digest and cipher functions in this header so we include // them for users that still expect that. -// -// TODO(fork): clean up callers so that they include what they use. #include "CCryptoBoringSSL_aead.h" #include "CCryptoBoringSSL_base64.h" #include "CCryptoBoringSSL_cipher.h" @@ -37,7 +35,7 @@ extern "C" { // EVP abstracts over public/private key algorithms. -// Public key objects. +// Public/private key objects. // // An |EVP_PKEY| object represents a public or private key. A given object may // be used concurrently on multiple threads by non-mutating functions, provided @@ -78,6 +76,13 @@ OPENSSL_EXPORT int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); // parameters or zero if not, or if the algorithm doesn't take parameters. OPENSSL_EXPORT int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey); +// EVP_PKEY_cmp_parameters compares the parameters of |a| and |b|. It returns +// one if they match, zero if not, or a negative number on error. +// +// WARNING: the return value differs from the usual return value convention. +OPENSSL_EXPORT int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, + const EVP_PKEY *b); + // EVP_PKEY_size returns the maximum size, in bytes, of a signature signed by // |pkey|. For an RSA key, this returns the number of bytes needed to represent // the modulus. For an EC key, this returns the maximum size of a DER-encoded @@ -89,14 +94,125 @@ OPENSSL_EXPORT int EVP_PKEY_size(const EVP_PKEY *pkey); // length of the group order. OPENSSL_EXPORT int EVP_PKEY_bits(const EVP_PKEY *pkey); +// The following constants are returned by |EVP_PKEY_id| and specify the type of +// key. +#define EVP_PKEY_NONE NID_undef +#define EVP_PKEY_RSA NID_rsaEncryption +#define EVP_PKEY_RSA_PSS NID_rsassaPss +#define EVP_PKEY_DSA NID_dsa +#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey +#define EVP_PKEY_ED25519 NID_ED25519 +#define EVP_PKEY_X25519 NID_X25519 +#define EVP_PKEY_HKDF NID_hkdf +#define EVP_PKEY_DH NID_dhKeyAgreement + // EVP_PKEY_id returns the type of |pkey|, which is one of the |EVP_PKEY_*| -// values. +// values above. These type values generally corresond to the algorithm OID, but +// not the parameters, of a SubjectPublicKeyInfo (RFC 5280) or PrivateKeyInfo +// (RFC 5208) AlgorithmIdentifier. Algorithm parameters can be inspected with +// algorithm-specific accessors, e.g. |EVP_PKEY_get_ec_curve_nid|. OPENSSL_EXPORT int EVP_PKEY_id(const EVP_PKEY *pkey); -// Getting and setting concrete public key types. -// -// The following functions get and set the underlying public key in an +// Algorithms. +// +// An |EVP_PKEY| may carry a key from one of several algorithms, represented by +// |EVP_PKEY_ALG|. |EVP_PKEY_ALG|s are used by functions that construct +// |EVP_PKEY|s, such as parsing, so that callers can specify the algorithm(s) to +// use. +// +// Each |EVP_PKEY_ALG| generally corresponds to the AlgorithmIdentifier of a +// SubjectPublicKeyInfo (RFC 5280) or PrivateKeyInfo (RFC 5208), but some may +// support multiple sets of AlgorithmIdentifier parameters, while others may be +// specific to one parameter. + +// EVP_pkey_rsa implements RSA keys (RFC 8017), encoded as rsaEncryption (RFC +// 3279, Section 2.3.1). The rsaEncryption encoding is confusingly named: these +// keys are used for all RSA operations, including signing. The |EVP_PKEY_id| +// value is |EVP_PKEY_RSA|. +// +// WARNING: This |EVP_PKEY_ALG| accepts all RSA key sizes supported by +// BoringSSL. When parsing RSA keys, callers should check the size is within +// their desired bounds with |EVP_PKEY_bits|. RSA public key operations scale +// quadratically and RSA private key operations scale cubicly, so key sizes may +// be a DoS vector. +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_rsa(void); + +// EVP_pkey_ec_* implement EC keys, encoded as id-ecPublicKey (RFC 5480, +// Section 2.1.1). The id-ecPublicKey encoding is confusingly named: it is also +// used for private keys (RFC 5915). The |EVP_PKEY_id| value is |EVP_PKEY_EC|. +// +// Each function only supports the specified curve, but curves are not reflected +// in |EVP_PKEY_id|. The curve can be inspected with +// |EVP_PKEY_get_ec_curve_nid|. +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_ec_p224(void); +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_ec_p256(void); +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_ec_p384(void); +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_ec_p521(void); + +// EVP_pkey_x25519 implements X25519 keys (RFC 7748), encoded as in RFC 8410. +// The |EVP_PKEY_id| value is |EVP_PKEY_X25519|. +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_x25519(void); + +// EVP_pkey_ed25519 implements Ed25519 keys (RFC 8032), encoded as in RFC 8410. +// The |EVP_PKEY_id| value is |EVP_PKEY_ED25519|. +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_ed25519(void); + +// EVP_pkey_dsa implements DSA keys, encoded as in RFC 3279, Section 2.3.2. The +// |EVP_PKEY_id| value is |EVP_PKEY_DSA|. This |EVP_PKEY_ALG| accepts all DSA +// parameters supported by BoringSSL. +// +// Keys of this type are not usable with any operations, though the underlying +// |DSA| object can be extracted with |EVP_PKEY_get0_DSA|. This key type is +// deprecated and only implemented for compatibility with legacy applications. +// +// TODO(crbug.com/42290364): We didn't wire up |EVP_PKEY_sign| and +// |EVP_PKEY_verify| just so it was auditable which callers used DSA. Once DSA +// is removed from the default SPKI and PKCS#8 parser and DSA users explicitly +// request |EVP_pkey_dsa|, we could change that. +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_dsa(void); + +// EVP_pkey_rsa_pss_sha256 implements RSASSA-PSS keys, encoded as id-RSASSA-PSS +// (RFC 4055, Section 3.1). The |EVP_PKEY_id| value is |EVP_PKEY_RSA_PSS|. This +// |EVP_PKEY_ALG| only accepts keys whose parameters specify: +// +// - A hashAlgorithm of SHA-256 +// - A maskGenAlgorithm of MGF1 with SHA-256 +// - A minimum saltLength of 32 +// - A trailerField of one (must be omitted in the encoding) +// +// Keys of this type will only be usable with RSASSA-PSS with matching signature +// parameters. +// +// This algorithm type is not recommended. The id-RSASSA-PSS key type is not +// widely implemented. Using it negates any compatibility benefits of using RSA. +// More modern algorithms like ECDSA are more performant and more compatible +// than id-RSASSA-PSS keys. This key type also adds significant complexity to a +// system. It has a wide range of possible parameter sets, so any uses must +// ensure all components not only support id-RSASSA-PSS, but also the specific +// parameters chosen. +// +// Note the id-RSASSA-PSS key type is distinct from the RSASSA-PSS signature +// algorithm. The widely implemented id-rsaEncryption key type (|EVP_pkey_rsa| +// and |EVP_PKEY_RSA|) also supports RSASSA-PSS signatures. +// +// WARNING: Any |EVP_PKEY|s produced by this algorithm will return a non-NULL +// |RSA| object through |EVP_PKEY_get1_RSA| and |EVP_PKEY_get0_RSA|. This is +// dangerous as existing code may assume a non-NULL return implies the more +// common id-rsaEncryption key. Additionally, the operations on the underlying +// |RSA| object will not capture the RSA-PSS constraints, so callers risk +// misusing the key by calling these functions. Callers using this algorithm +// must use |EVP_PKEY_id| to distinguish |EVP_PKEY_RSA| and |EVP_PKEY_RSA_PSS|. +// +// WARNING: BoringSSL does not currently implement |RSA_get0_pss_params| with +// these keys. Callers that require this functionality should contact the +// BoringSSL team. +OPENSSL_EXPORT const EVP_PKEY_ALG *EVP_pkey_rsa_pss_sha256(void); + + +// Getting and setting concrete key types. +// +// The following functions get and set the underlying key representation in an // |EVP_PKEY| object. The |set1| functions take an additional reference to the // underlying key and return one on success or zero if |key| is NULL. The // |assign| functions adopt the caller's reference and return one on success or @@ -108,6 +224,18 @@ OPENSSL_EXPORT int EVP_PKEY_id(const EVP_PKEY *pkey); // non-mutating for thread-safety purposes, but mutating functions on the // returned lower-level objects are considered to also mutate the |EVP_PKEY| and // may not be called concurrently with other operations on the |EVP_PKEY|. +// +// WARNING: Matching OpenSSL, the RSA functions behave non-uniformly. +// |EVP_PKEY_set1_RSA| and |EVP_PKEY_assign_RSA| construct an |EVP_PKEY_RSA| +// key, while the |EVP_PKEY_get0_RSA| and |EVP_PKEY_get1_RSA| will return +// non-NULL for both |EVP_PKEY_RSA| and |EVP_PKEY_RSA_PSS|. +// +// This means callers risk misusing a key if they assume a non-NULL return from +// |EVP_PKEY_get0_RSA| or |EVP_PKEY_get1_RSA| implies |EVP_PKEY_RSA|. Prefer +// |EVP_PKEY_id| to check the type of a key. To reduce this risk, BoringSSL does +// not make |EVP_PKEY_RSA_PSS| available by default, only when callers opt in +// via |EVP_pkey_rsa_pss_sha256|. This differs from upstream OpenSSL, where +// callers are exposed to |EVP_PKEY_RSA_PSS| by default. OPENSSL_EXPORT int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key); OPENSSL_EXPORT int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key); @@ -129,39 +257,36 @@ OPENSSL_EXPORT int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key); OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey); OPENSSL_EXPORT DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey); -#define EVP_PKEY_NONE NID_undef -#define EVP_PKEY_RSA NID_rsaEncryption -#define EVP_PKEY_RSA_PSS NID_rsassaPss -#define EVP_PKEY_DSA NID_dsa -#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey -#define EVP_PKEY_ED25519 NID_ED25519 -#define EVP_PKEY_X25519 NID_X25519 -#define EVP_PKEY_HKDF NID_hkdf -#define EVP_PKEY_DH NID_dhKeyAgreement - -// EVP_PKEY_set_type sets the type of |pkey| to |type|. It returns one if -// successful or zero if the |type| argument is not one of the |EVP_PKEY_*| -// values. If |pkey| is NULL, it simply reports whether the type is known. -OPENSSL_EXPORT int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); - -// EVP_PKEY_cmp_parameters compares the parameters of |a| and |b|. It returns -// one if they match, zero if not, or a negative number of on error. -// -// WARNING: the return value differs from the usual return value convention. -OPENSSL_EXPORT int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, - const EVP_PKEY *b); - // ASN.1 functions +// EVP_PKEY_from_subject_public_key_info decodes a DER-encoded +// SubjectPublicKeyInfo structure (RFC 5280) from |in|. It returns a +// newly-allocated |EVP_PKEY| or NULL on error. Only the |num_algs| algorithms +// in |algs| will be considered when parsing. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_from_subject_public_key_info( + const uint8_t *in, size_t len, const EVP_PKEY_ALG *const *algs, + size_t num_algs); + // EVP_parse_public_key decodes a DER-encoded SubjectPublicKeyInfo structure // (RFC 5280) from |cbs| and advances |cbs|. It returns a newly-allocated -// |EVP_PKEY| or NULL on error. If the key is an EC key, the curve is guaranteed -// to be set. +// |EVP_PKEY| or NULL on error. +// +// Prefer |EVP_PKEY_from_subject_public_key_info| instead. This function has +// several pitfalls: +// +// Callers are expected to handle trailing data retuned from |cbs|, making more +// common cases error-prone. // -// The caller must check the type of the parsed public key to ensure it is -// suitable and validate other desired key properties such as RSA modulus size -// or EC curve. +// There is also no way to pass in supported algorithms. This function instead +// supports some default set of algorithms. Future versions of BoringSSL may add +// to this list, based on the needs of the other callers. Conversely, some +// algorithms may be intentionally omitted, if they cause too much risk to +// existing callers. +// +// This means callers must check the type of the parsed public key to ensure it +// is suitable and validate other desired key properties such as RSA modulus +// size or EC curve. OPENSSL_EXPORT EVP_PKEY *EVP_parse_public_key(CBS *cbs); // EVP_marshal_public_key marshals |key| as a DER-encoded SubjectPublicKeyInfo @@ -169,19 +294,41 @@ OPENSSL_EXPORT EVP_PKEY *EVP_parse_public_key(CBS *cbs); // success and zero on error. OPENSSL_EXPORT int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key); +// EVP_PKEY_from_private_key_info decodes a DER-encoded PrivateKeyInfo structure +// (RFC 5208) from |in|. It returns a newly-allocated |EVP_PKEY| or NULL on +// error. Only the |num_algs| algorithms in |algs| will be considered when +// parsing. +// +// A PrivateKeyInfo ends with an optional set of attributes. These are silently +// ignored. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_from_private_key_info( + const uint8_t *in, size_t len, const EVP_PKEY_ALG *const *algs, + size_t num_algs); + // EVP_parse_private_key decodes a DER-encoded PrivateKeyInfo structure (RFC // 5208) from |cbs| and advances |cbs|. It returns a newly-allocated |EVP_PKEY| // or NULL on error. // -// The caller must check the type of the parsed private key to ensure it is -// suitable and validate other desired key properties such as RSA modulus size -// or EC curve. In particular, RSA private key operations scale cubicly, so +// Prefer |EVP_PKEY_from_private_key_info| instead. This function has +// several pitfalls: +// +// Callers are expected to handle trailing data retuned from |cbs|, making more +// common cases error-prone. +// +// There is also no way to pass in supported algorithms. This function instead +// supports some default set of algorithms. Future versions of BoringSSL may add +// to this list, based on the needs of the other callers. Conversely, some +// algorithms may be intentionally omitted, if they cause too much risk to +// existing callers. +// +// This means the caller must check the type of the parsed private key to ensure +// it is suitable and validate other desired key properties such as RSA modulus +// size or EC curve. In particular, RSA private key operations scale cubicly, so // applications accepting RSA private keys from external sources may need to // bound key sizes (use |EVP_PKEY_bits| or |RSA_bits|) to avoid a DoS vector. // -// A PrivateKeyInfo ends with an optional set of attributes. These are not -// processed and so this function will silently ignore any trailing data in the -// structure. +// A PrivateKeyInfo ends with an optional set of attributes. These are silently +// ignored. OPENSSL_EXPORT EVP_PKEY *EVP_parse_private_key(CBS *cbs); // EVP_marshal_private_key marshals |key| as a DER-encoded PrivateKeyInfo @@ -197,20 +344,18 @@ OPENSSL_EXPORT int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key); // RFC 7748 and RFC 8032, respectively. Note the RFC 8032 private key format is // the 32-byte prefix of |ED25519_sign|'s 64-byte private key. -// EVP_PKEY_new_raw_private_key returns a newly allocated |EVP_PKEY| wrapping a -// private key of the specified type. It returns one on success and zero on -// error. -OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *unused, +// EVP_PKEY_from_raw_private_key interprets |in| as a raw private key of type +// |alg| and returns a newly-allocated |EVP_PKEY|, or nullptr on error. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_from_raw_private_key(const EVP_PKEY_ALG *alg, + const uint8_t *in, + size_t len); + +// EVP_PKEY_from_raw_public_key interprets |in| as a raw public key of type +// |alg| and returns a newly-allocated |EVP_PKEY|, or nullptr on error. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_from_raw_public_key(const EVP_PKEY_ALG *alg, const uint8_t *in, size_t len); -// EVP_PKEY_new_raw_public_key returns a newly allocated |EVP_PKEY| wrapping a -// public key of the specified type. It returns one on success and zero on -// error. -OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *unused, - const uint8_t *in, - size_t len); - // EVP_PKEY_get_raw_private_key outputs the private key for |pkey| in raw form. // If |out| is NULL, it sets |*out_len| to the size of the raw private key. // Otherwise, it writes at most |*out_len| bytes to |out| and sets |*out_len| to @@ -468,10 +613,33 @@ OPENSSL_EXPORT int EVP_PBE_scrypt(const char *password, size_t password_len, size_t key_len); -// Public key contexts. +// Operations. +// +// |EVP_PKEY_CTX| objects hold the context for an operation (e.g. signing or +// encrypting) that uses an |EVP_PKEY|. They are used to configure +// algorithm-specific parameters for the operation before performing the +// operation. The general pattern for performing an operation in EVP is: +// +// 1. Construct an |EVP_PKEY_CTX|, either with |EVP_PKEY_CTX_new| (operations +// using a key, like signing) or |EVP_PKEY_CTX_new_id| (operations not using +// an existing key, like key generation). +// +// 2. Initialize it for an operation. For example, |EVP_PKEY_sign_init| +// initializes an |EVP_PKEY_CTX| for signing. // -// |EVP_PKEY_CTX| objects hold the context of an operation (e.g. signing or -// encrypting) that uses a public key. +// 3. Configure algorithm-specific parameters for the operation by calling +// control functions on the |EVP_PKEY_CTX|. Some functions are generic, such +// as |EVP_PKEY_CTX_set_signature_md|, and some are specific to an algorithm, +// such as |EVP_PKEY_CTX_set_rsa_padding|. +// +// 4. Perform the operation. For example, |EVP_PKEY_sign| signs with the +// corresponding parameters. +// +// 5. Release the |EVP_PKEY_CTX| with |EVP_PKEY_CTX_free|. +// +// Each |EVP_PKEY| algorithm interprets operations and parameters differently. +// Not all algorithms support all operations. Functions will fail if the +// algorithm does not support the parameter or operation. // EVP_PKEY_CTX_new allocates a fresh |EVP_PKEY_CTX| for use with |pkey|. It // returns the context or NULL on error. @@ -686,16 +854,16 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding); // EVP_PKEY_CTX_set_rsa_pss_saltlen sets the length of the salt in a PSS-padded -// signature. A value of -1 cause the salt to be the same length as the digest -// in the signature. A value of -2 causes the salt to be the maximum length -// that will fit when signing and recovered from the signature when verifying. -// Otherwise the value gives the size of the salt in bytes. +// signature. A value of |RSA_PSS_SALTLEN_DIGEST| causes the salt to be the same +// length as the digest in the signature. A value of |RSA_PSS_SALTLEN_AUTO| +// causes the salt to be the maximum length that will fit when signing and +// recovered from the signature when verifying. Otherwise the value gives the +// size of the salt in bytes. // -// If unsure, use -1. +// If unsure, use |RSA_PSS_SALTLEN_DIGEST|, which is the default. Note this +// differs from OpenSSL, which defaults to |RSA_PSS_SALTLEN_AUTO|. // // Returns one on success or zero on error. -// -// TODO(davidben): The default is currently -2. Switch it to -1. OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len); @@ -715,7 +883,9 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits); // EVP_PKEY_CTX_set_rsa_keygen_pubexp sets |e| as the public exponent for key -// generation. Returns one on success or zero on error. +// generation. Returns one on success or zero on error. On success, |ctx| takes +// ownership of |e|. The library will then call |BN_free| on |e| when |ctx| is +// destroyed. OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *e); @@ -766,6 +936,14 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, // EC specific control functions. +// EVP_PKEY_get_ec_curve_nid returns |pkey|'s curve as a NID constant, such as +// |NID_X9_62_prime256v1|, or |NID_undef| if |pkey| is not an EC key. +OPENSSL_EXPORT int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey); + +// EVP_PKEY_get_ec_point_conv_form returns |pkey|'s point conversion form as a +// |POINT_CONVERSION_*| constant, or zero if |pkey| is not an EC key. +OPENSSL_EXPORT int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey); + // EVP_PKEY_CTX_set_ec_paramgen_curve_nid sets the curve used for // |EVP_PKEY_keygen| or |EVP_PKEY_paramgen| operations to |nid|. It returns one // on success and zero on error. @@ -893,6 +1071,25 @@ OPENSSL_EXPORT EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out, OPENSSL_EXPORT int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int encoding); +// EVP_PKEY_set_type sets the type of |pkey| to |type|. It returns one if +// successful or zero if the |type| argument is not one of the |EVP_PKEY_*| +// values supported for use with this function. If |pkey| is NULL, it simply +// reports whether the type is known. +// +// There are very few cases where this function is useful. Changing |pkey|'s +// type clears any previously stored keys, so there is no benefit to loading a +// key and then changing its type. Although |pkey| is left with a type +// configured, it has no key, and functions which set a key, such as +// |EVP_PKEY_set1_RSA|, will configure a type anyway. If writing unit tests that +// are only sensitive to the type of a key, it is preferable to construct a real +// key, so that tests are more representative of production code. +// +// The only API pattern which requires this function is +// |EVP_PKEY_set1_tls_encodedpoint| with X25519, which requires a half-empty +// |EVP_PKEY| that was first configured with |EVP_PKEY_X25519|. Currently, all +// other values of |type| will result in an error. +OPENSSL_EXPORT int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); + // EVP_PKEY_set1_tls_encodedpoint replaces |pkey| with a public key encoded by // |in|. It returns one on success and zero on error. // @@ -1004,6 +1201,26 @@ OPENSSL_EXPORT int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); // EVP_PKEY_type returns |nid|. OPENSSL_EXPORT int EVP_PKEY_type(int nid); +// EVP_PKEY_new_raw_private_key interprets |in| as a raw private key of type +// |type|, which must be an |EVP_PKEY_*| constant, such as |EVP_PKEY_X25519|, +// and returns a newly-allocated |EVP_PKEY|, or nullptr on error. +// +// Prefer |EVP_PKEY_from_raw_private_key|, which allows dead code elimination to +// discard algorithms that aren't reachable from the caller. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *unused, + const uint8_t *in, + size_t len); + +// EVP_PKEY_new_raw_public_key interprets |in| as a raw public key of type +// |type|, which must be an |EVP_PKEY_*| constant, such as |EVP_PKEY_X25519|, +// and returns a newly-allocated |EVP_PKEY|, or nullptr on error. +// +// Prefer |EVP_PKEY_from_raw_private_key|, which allows dead code elimination to +// discard algorithms that aren't reachable from the caller. +OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *unused, + const uint8_t *in, + size_t len); + // Preprocessor compatibility section (hidden). // diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp_errors.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp_errors.h index c7fa18055..9626caff0 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp_errors.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_evp_errors.h @@ -21,7 +21,7 @@ #define EVP_R_DIFFERENT_KEY_TYPES 103 #define EVP_R_DIFFERENT_PARAMETERS 104 #define EVP_R_ENCODE_ERROR 105 -#define EVP_R_EXPECTING_AN_EC_KEY_KEY 106 +#define EVP_R_EXPECTING_A_EC_KEY 106 #define EVP_R_EXPECTING_AN_RSA_KEY 107 #define EVP_R_EXPECTING_A_DSA_KEY 108 #define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 109 diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_hpke.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_hpke.h index ae7db6db5..739653015 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_hpke.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_hpke.h @@ -16,7 +16,7 @@ #define OPENSSL_HEADER_HPKE_H #include "CCryptoBoringSSL_aead.h" -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export #include "CCryptoBoringSSL_curve25519.h" #include "CCryptoBoringSSL_digest.h" @@ -42,12 +42,14 @@ extern "C" { // The following constants are KEM identifiers. #define EVP_HPKE_DHKEM_P256_HKDF_SHA256 0x0010 #define EVP_HPKE_DHKEM_X25519_HKDF_SHA256 0x0020 +#define EVP_HPKE_XWING 0x647a // The following functions are KEM algorithms which may be used with HPKE. Note // that, while some HPKE KEMs use KDFs internally, this is separate from the // |EVP_HPKE_KDF| selection. OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_x25519_hkdf_sha256(void); OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_p256_hkdf_sha256(void); +OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_xwing(void); // EVP_HPKE_KEM_id returns the HPKE KEM identifier for |kem|, which // will be one of the |EVP_HPKE_KEM_*| constants. @@ -55,7 +57,7 @@ OPENSSL_EXPORT uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem); // EVP_HPKE_MAX_PUBLIC_KEY_LENGTH is the maximum length of an encoded public key // for all KEMs currently supported by this library. -#define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 65 +#define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 1216 // EVP_HPKE_KEM_public_key_len returns the length of a public key for |kem|. // This value will be at most |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH|. @@ -71,7 +73,7 @@ OPENSSL_EXPORT size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem); // EVP_HPKE_MAX_ENC_LENGTH is the maximum length of "enc", the encapsulated // shared secret, for all KEMs currently supported by this library. -#define EVP_HPKE_MAX_ENC_LENGTH 65 +#define EVP_HPKE_MAX_ENC_LENGTH 1120 // EVP_HPKE_KEM_enc_len returns the length of the "enc", the encapsulated shared // secret, for |kem|. This value will be at most |EVP_HPKE_MAX_ENC_LENGTH|. diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_mldsa.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_mldsa.h index 88b12927d..f2b906741 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_mldsa.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_mldsa.h @@ -318,6 +318,146 @@ OPENSSL_EXPORT int MLDSA87_parse_public_key( struct MLDSA87_public_key *public_key, CBS *in); +// ML-DSA-44. + +// MLDSA44_private_key contains an ML-DSA-44 private key. The contents of this +// object should never leave the address space since the format is unstable. +struct MLDSA44_private_key { + union { + uint8_t bytes[32 + 32 + 64 + 256 * 4 * (4 + 4 + 4)]; + uint32_t alignment; + } opaque; +}; + +// MLDSA44_public_key contains an ML-DSA-44 public key. The contents of this +// object should never leave the address space since the format is unstable. +struct MLDSA44_public_key { + union { + uint8_t bytes[32 + 64 + 256 * 4 * 4]; + uint32_t alignment; + } opaque; +}; + +// MLDSA44_prehash contains a pre-hash context for ML-DSA-44. The contents of +// this object should never leave the address space since the format is +// unstable. +struct MLDSA44_prehash { + union { + uint8_t bytes[200 + 4 + 4 + 4 * sizeof(size_t)]; + uint64_t alignment; + } opaque; +}; + +// MLDSA44_PRIVATE_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// private key. +#define MLDSA44_PRIVATE_KEY_BYTES 2560 + +// MLDSA44_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-DSA-44 +// public key. +#define MLDSA44_PUBLIC_KEY_BYTES 1312 + +// MLDSA44_SIGNATURE_BYTES is the number of bytes in an encoded ML-DSA-44 +// signature. +#define MLDSA44_SIGNATURE_BYTES 2420 + +// MLDSA44_generate_key generates a random public/private key pair, writes the +// encoded public key to |out_encoded_public_key|, writes the seed to +// |out_seed|, and sets |out_private_key| to the private key. Returns 1 on +// success and 0 on allocation failure. +OPENSSL_EXPORT int MLDSA44_generate_key( + uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES], + uint8_t out_seed[MLDSA_SEED_BYTES], + struct MLDSA44_private_key *out_private_key); + +// MLDSA44_private_key_from_seed regenerates a private key from a seed value +// that was generated by |MLDSA44_generate_key|. Returns 1 on success and 0 on +// allocation failure or if |seed_len| is incorrect. +OPENSSL_EXPORT int MLDSA44_private_key_from_seed( + struct MLDSA44_private_key *out_private_key, const uint8_t *seed, + size_t seed_len); + +// MLDSA44_public_from_private sets |*out_public_key| to the public key that +// corresponds to |private_key|. Returns 1 on success and 0 on failure. +OPENSSL_EXPORT int MLDSA44_public_from_private( + struct MLDSA44_public_key *out_public_key, + const struct MLDSA44_private_key *private_key); + +// MLDSA44_sign generates a signature for the message |msg| of length +// |msg_len| using |private_key| (following the randomized algorithm), and +// writes the encoded signature to |out_encoded_signature|. The |context| +// argument is also signed over and can be used to include implicit contextual +// information that isn't included in |msg|. The same value of |context| must be +// presented to |MLDSA44_verify| in order for the generated signature to be +// considered valid. |context| and |context_len| may be |NULL| and 0 to use an +// empty context (this is common). Returns 1 on success and 0 on failure. +OPENSSL_EXPORT int MLDSA44_sign( + uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, const uint8_t *msg, + size_t msg_len, const uint8_t *context, size_t context_len); + +// MLDSA44_verify verifies that |signature| constitutes a valid +// signature for the message |msg| of length |msg_len| using |public_key|. The +// value of |context| must equal the value that was passed to |MLDSA44_sign| +// when the signature was generated. Returns 1 on success or 0 on error. +OPENSSL_EXPORT int MLDSA44_verify(const struct MLDSA44_public_key *public_key, + const uint8_t *signature, + size_t signature_len, const uint8_t *msg, + size_t msg_len, const uint8_t *context, + size_t context_len); + +// MLDSA44_prehash_init initializes a pre-hashing state using |public_key|. The +// |context| argument can be used to include implicit contextual information +// that isn't included in the message. The same value of |context| must be +// presented to |MLDSA44_verify| in order for the generated signature to be +// considered valid. |context| and |context_len| may be |NULL| and 0 to use an +// empty context (this is common). Returns 1 on success and 0 on failure (if the +// context is too long). +OPENSSL_EXPORT int MLDSA44_prehash_init( + struct MLDSA44_prehash *out_state, + const struct MLDSA44_public_key *public_key, const uint8_t *context, + size_t context_len); + +// MLDSA44_prehash_update incorporates the given |msg| of length |msg_len| into +// the pre-hashing state. This can be called multiple times on successive chunks +// of the message. This should be called after |MLDSA44_prehash_init| and before +// |MLDSA44_prehash_finalize|. +OPENSSL_EXPORT void MLDSA44_prehash_update(struct MLDSA44_prehash *inout_state, + const uint8_t *msg, size_t msg_len); + +// MLDSA44_prehash_finalize extracts a pre-hashed message representative from +// the given pre-hashing state. This should be called after +// |MLDSA44_prehash_init| and |MLDSA44_prehash_update|. The resulting +// |out_msg_rep| should then be passed to |MLDSA44_sign_message_representative| +// to obtain a signature. +OPENSSL_EXPORT void MLDSA44_prehash_finalize( + uint8_t out_msg_rep[MLDSA_MU_BYTES], struct MLDSA44_prehash *inout_state); + +// MLDSA44_sign_message_representative generates a signature for the pre-hashed +// message |msg_rep| using |private_key| (following the randomized algorithm), +// and writes the encoded signature to |out_encoded_signature|. The |msg_rep| +// should be obtained via calls to |MLDSA44_prehash_init|, +// |MLDSA44_prehash_update| and |MLDSA44_prehash_finalize| using the public key +// from the same key pair, otherwise the signature will not verify. Returns 1 on +// success and 0 on failure. +OPENSSL_EXPORT int MLDSA44_sign_message_representative( + uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES], + const struct MLDSA44_private_key *private_key, + const uint8_t msg_rep[MLDSA_MU_BYTES]); + +// MLDSA44_marshal_public_key serializes |public_key| to |out| in the standard +// format for ML-DSA-44 public keys. It returns 1 on success or 0 on +// allocation error. +OPENSSL_EXPORT int MLDSA44_marshal_public_key( + CBB *out, const struct MLDSA44_public_key *public_key); + +// MLDSA44_parse_public_key parses a public key, in the format generated by +// |MLDSA44_marshal_public_key|, from |in| and writes the result to +// |out_public_key|. It returns 1 on success or 0 on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int MLDSA44_parse_public_key( + struct MLDSA44_public_key *public_key, CBS *in); + + #if defined(__cplusplus) } // extern C #endif diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_nid.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_nid.h index 415556daf..f7fc5ab29 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_nid.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_nid.h @@ -17,7 +17,7 @@ #ifndef OPENSSL_HEADER_NID_H #define OPENSSL_HEADER_NID_H -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -4216,6 +4216,9 @@ extern "C" { #define SN_X25519MLKEM768 "X25519MLKEM768" #define NID_X25519MLKEM768 965 +#define SN_MLKEM1024 "MLKEM1024" +#define NID_MLKEM1024 966 + #if defined(__cplusplus) } /* extern C */ diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_rsa.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_rsa.h index e7516e0f7..a6f8425d8 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_rsa.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_rsa.h @@ -69,9 +69,7 @@ OPENSSL_EXPORT int RSA_up_ref(RSA *rsa); // Properties. // OPENSSL_RSA_MAX_MODULUS_BITS is the maximum supported RSA modulus, in bits. -// -// TODO(crbug.com/402677800): Reduce this to 8192. -#define OPENSSL_RSA_MAX_MODULUS_BITS 16384 +#define OPENSSL_RSA_MAX_MODULUS_BITS 8192 // RSA_bits returns the size of |rsa|, in bits. OPENSSL_EXPORT unsigned RSA_bits(const RSA *rsa); @@ -225,7 +223,11 @@ OPENSSL_EXPORT int RSA_generate_key_fips(RSA *rsa, int bits, BN_GENCB *cb); // It returns 1 on success or zero on error. // // The |padding| argument must be one of the |RSA_*_PADDING| values. If in -// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. +// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. When |padding| is +// |RSA_PKCS1_OAEP_PADDING|, this function has no way to set the OAEP or MGF-1 +// digest, so it is always SHA-1. For other OAEP parameters, wrap |rsa| in an +// |EVP_PKEY| and use |EVP_PKEY_encrypt| with |EVP_PKEY_CTX_set_rsa_padding| and +// related functions. OPENSSL_EXPORT int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding); @@ -237,7 +239,11 @@ OPENSSL_EXPORT int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, // It returns 1 on success or zero on error. // // The |padding| argument must be one of the |RSA_*_PADDING| values. If in -// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. +// doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. When |padding| is +// |RSA_PKCS1_OAEP_PADDING|, this function has no way to set the OAEP or MGF-1 +// digest, so it is always SHA-1. For other OAEP parameters, wrap |rsa| in an +// |EVP_PKEY| and use |EVP_PKEY_decrypt| with |EVP_PKEY_CTX_set_rsa_padding| and +// related functions. // // WARNING: Passing |RSA_PKCS1_PADDING| into this function is deprecated and // insecure. RSAES-PKCS1-v1_5 is vulnerable to a chosen-ciphertext attack. @@ -259,6 +265,11 @@ OPENSSL_EXPORT int RSA_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, // -1 on error. The |padding| argument must be one of the |RSA_*_PADDING| // values. If in doubt, use |RSA_PKCS1_OAEP_PADDING| for new protocols. // +// When |padding| is |RSA_PKCS1_OAEP_PADDING|, this function has no way to set +// the OAEP or MGF-1 digest, so it is always SHA-1. For other OAEP parameters, +// wrap |rsa| in an |EVP_PKEY| and use |EVP_PKEY_encrypt| with +// |EVP_PKEY_CTX_set_rsa_padding| and related functions. +// // WARNING: this function is dangerous because it breaks the usual return value // convention. Use |RSA_encrypt| instead. OPENSSL_EXPORT int RSA_public_encrypt(size_t flen, const uint8_t *from, @@ -272,6 +283,11 @@ OPENSSL_EXPORT int RSA_public_encrypt(size_t flen, const uint8_t *from, // |RSA_PKCS1_PADDING| into this function is deprecated and insecure. See // |RSA_decrypt|. // +// When |padding| is |RSA_PKCS1_OAEP_PADDING|, this function has no way to set +// the OAEP or MGF-1 digest, so it is always SHA-1. For other OAEP parameters, +// wrap |rsa| in an |EVP_PKEY| and use |EVP_PKEY_decrypt| with +// |EVP_PKEY_CTX_set_rsa_padding| and related functions. +// // WARNING: this function is dangerous because it breaks the usual return value // convention. Use |RSA_decrypt| instead. OPENSSL_EXPORT int RSA_private_decrypt(size_t flen, const uint8_t *from, @@ -301,6 +317,15 @@ OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *digest, size_t digest_len, uint8_t *out, unsigned *out_len, RSA *rsa); +// RSA_PSS_SALTLEN_DIGEST indicates a PSS salt length that matches the digest +// length. This is recommended. +#define RSA_PSS_SALTLEN_DIGEST (-1) +// RSA_PSS_SALTLEN_AUTO indicates a maximum possible PSS salt length when +// signing, and automatically detecting the salt length when verifying. This is +// not recommended. Neither the signing nor verifying behaviors are compliant +// with FIPS 186-5. +#define RSA_PSS_SALTLEN_AUTO (-2) + // RSA_sign_pss_mgf1 signs |digest_len| bytes from |digest| with the public key // from |rsa| using RSASSA-PSS with MGF1 as the mask generation function. It // writes, at most, |max_out| bytes of signature data to |out|. The |max_out| @@ -311,9 +336,10 @@ OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *digest, // and the MGF1 hash, respectively. If |mgf1_md| is NULL, |md| is // used. // -// |salt_len| specifies the expected salt length in bytes. If |salt_len| is -1, -// then the salt length is the same as the hash length. If -2, then the salt -// length is maximal given the size of |rsa|. If unsure, use -1. +// |salt_len| specifies the expected salt length in bytes. If |salt_len| is +// |RSA_PSS_SALTLEN_DIGEST|, then the salt length is the same as the hash +// length. If |RSA_PSS_SALTLEN_AUTO|, then the salt length is maximal given the +// size of |rsa|. If unsure, use |RSA_PSS_SALTLEN_DIGEST|. // // WARNING: |digest| must be the result of hashing the data to be signed with // |md|. Passing unhashed inputs will not result in a secure signature scheme. @@ -373,9 +399,9 @@ OPENSSL_EXPORT int RSA_verify(int hash_nid, const uint8_t *digest, // and the MGF1 hash, respectively. If |mgf1_md| is NULL, |md| is // used. |salt_len| specifies the expected salt length in bytes. // -// If |salt_len| is -1, then the salt length is the same as the hash length. If -// -2, then the salt length is recovered and all values accepted. If unsure, use -// -1. +// If |salt_len| is |RSA_PSS_SALTLEN_DIGEST|, then the salt length is the same +// as the hash length. If |RSA_PSS_SALTLEN_AUTO|, then the salt length is +// recovered and all values accepted. If unsure, use |RSA_PSS_SALTLEN_DIGEST|. // // WARNING: |digest| must be the result of hashing the data to be verified with // |md|. Passing unhashed input will not result in a secure signature scheme. @@ -737,8 +763,13 @@ OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP(uint8_t *to, size_t to_len, OPENSSL_EXPORT int RSA_print(BIO *bio, const RSA *rsa, int indent); // RSA_get0_pss_params returns NULL. In OpenSSL, this function retries RSA-PSS -// parameters associated with |RSA| objects, but BoringSSL does not support -// the id-RSASSA-PSS key encoding. +// parameters associated with |RSA| objects, but BoringSSL does not enable the +// id-RSASSA-PSS key encoding by default. +// +// WARNING: BoringSSL does support id-RSASSA-PSS parameters when callers opt in +// (see |EVP_pkey_rsa_pss_sha256|). We currently assume such callers do not need +// this function. Callers that opt into id-RSASSA-PSS support and require this +// functionality should contact the BoringSSL team. OPENSSL_EXPORT const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *rsa); // RSA_new_method_no_e returns a newly-allocated |RSA| object backed by diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha.h index 33a8a76ca..2b1f6b40d 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha.h @@ -15,8 +15,13 @@ #ifndef OPENSSL_HEADER_SHA_H #define OPENSSL_HEADER_SHA_H -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export -#include "CCryptoBoringSSL_bcm_public.h" // IWYU pragma: export +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_bcm_public.h" // IWYU pragma: export + +// `sha.h` historically included SHA-1 and SHA-2 hash functions. So, for +// backward compatibility `sha2.h` is included here. New uses of this header +// should include sha2.h unless SHA-1 family functions are required. +#include "CCryptoBoringSSL_sha2.h" // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -74,160 +79,6 @@ OPENSSL_EXPORT void CRYPTO_fips_186_2_prf( uint8_t *out, size_t out_len, const uint8_t xkey[SHA_DIGEST_LENGTH]); -// SHA-224. - -// SHA224_CBLOCK is the block size of SHA-224. -#define SHA224_CBLOCK 64 - -// SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. -#define SHA224_DIGEST_LENGTH 28 - -// SHA224_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha); - -// SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); - -// SHA224_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. It -// returns 1. -OPENSSL_EXPORT int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], - SHA256_CTX *sha); - -// SHA224 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, - uint8_t out[SHA224_DIGEST_LENGTH]); - - -// SHA-256. - -// SHA256_CBLOCK is the block size of SHA-256. -#define SHA256_CBLOCK 64 - -// SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. -#define SHA256_DIGEST_LENGTH 32 - -// SHA256_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha); - -// SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); - -// SHA256_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. It -// returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA256_Final(uint8_t out[SHA256_DIGEST_LENGTH], - SHA256_CTX *sha); - -// SHA256 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, - uint8_t out[SHA256_DIGEST_LENGTH]); - -// SHA256_Transform is a low-level function that performs a single, SHA-256 -// block transformation using the state from |sha| and |SHA256_CBLOCK| bytes -// from |block|. -OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, - const uint8_t block[SHA256_CBLOCK]); - -// SHA256_TransformBlocks is a low-level function that takes |num_blocks| * -// |SHA256_CBLOCK| bytes of data and performs SHA-256 transforms on it to update -// |state|. You should not use this function unless you are implementing a -// derivative of SHA-256. -OPENSSL_EXPORT void SHA256_TransformBlocks(uint32_t state[8], - const uint8_t *data, - size_t num_blocks); - - -// SHA-384. - -// SHA384_CBLOCK is the block size of SHA-384. -#define SHA384_CBLOCK 128 - -// SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. -#define SHA384_DIGEST_LENGTH 48 - -// SHA384_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha); - -// SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); - -// SHA384_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. It -// returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], - SHA512_CTX *sha); - -// SHA384 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, - uint8_t out[SHA384_DIGEST_LENGTH]); - - -// SHA-512. - -// SHA512_CBLOCK is the block size of SHA-512. -#define SHA512_CBLOCK 128 - -// SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. -#define SHA512_DIGEST_LENGTH 64 - -// SHA512_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha); - -// SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); - -// SHA512_Final adds the final padding to |sha| and writes the resulting digest -// to |out|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. It -// returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], - SHA512_CTX *sha); - -// SHA512 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, - uint8_t out[SHA512_DIGEST_LENGTH]); - -// SHA512_Transform is a low-level function that performs a single, SHA-512 -// block transformation using the state from |sha| and |SHA512_CBLOCK| bytes -// from |block|. -OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, - const uint8_t block[SHA512_CBLOCK]); - - -// SHA-512-256 -// -// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6 - -#define SHA512_256_DIGEST_LENGTH 32 - -// SHA512_256_Init initialises |sha| and returns 1. -OPENSSL_EXPORT int SHA512_256_Init(SHA512_CTX *sha); - -// SHA512_256_Update adds |len| bytes from |data| to |sha| and returns 1. -OPENSSL_EXPORT int SHA512_256_Update(SHA512_CTX *sha, const void *data, - size_t len); - -// SHA512_256_Final adds the final padding to |sha| and writes the resulting -// digest to |out|, which must have at least |SHA512_256_DIGEST_LENGTH| bytes of -// space. It returns one on success and zero on programmer error. -OPENSSL_EXPORT int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], - SHA512_CTX *sha); - -// SHA512_256 writes the digest of |len| bytes from |data| to |out| and returns -// |out|. There must be at least |SHA512_256_DIGEST_LENGTH| bytes of space in -// |out|. -OPENSSL_EXPORT uint8_t *SHA512_256(const uint8_t *data, size_t len, - uint8_t out[SHA512_256_DIGEST_LENGTH]); - - #if defined(__cplusplus) } // extern C #endif diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha2.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha2.h new file mode 100644 index 000000000..e05626055 --- /dev/null +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_sha2.h @@ -0,0 +1,184 @@ +// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef OPENSSL_HEADER_SHA2_H +#define OPENSSL_HEADER_SHA2_H + +#include "CCryptoBoringSSL_base.h" // IWYU pragma: export +#include "CCryptoBoringSSL_bcm_public.h" // IWYU pragma: export + +#if defined(__cplusplus) +extern "C" { +#endif + + +// SHA-224. + +// SHA224_CBLOCK is the block size of SHA-224. +#define SHA224_CBLOCK 64 + +// SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. +#define SHA224_DIGEST_LENGTH 28 + +// SHA224_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha); + +// SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); + +// SHA224_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. It +// returns 1. +OPENSSL_EXPORT int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], + SHA256_CTX *sha); + +// SHA224 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, + uint8_t out[SHA224_DIGEST_LENGTH]); + + +// SHA-256. + +// SHA256_CBLOCK is the block size of SHA-256. +#define SHA256_CBLOCK 64 + +// SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. +#define SHA256_DIGEST_LENGTH 32 + +// SHA256_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha); + +// SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); + +// SHA256_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA256_Final(uint8_t out[SHA256_DIGEST_LENGTH], + SHA256_CTX *sha); + +// SHA256 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, + uint8_t out[SHA256_DIGEST_LENGTH]); + +// SHA256_Transform is a low-level function that performs a single, SHA-256 +// block transformation using the state from |sha| and |SHA256_CBLOCK| bytes +// from |block|. +OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, + const uint8_t block[SHA256_CBLOCK]); + +// SHA256_TransformBlocks is a low-level function that takes |num_blocks| * +// |SHA256_CBLOCK| bytes of data and performs SHA-256 transforms on it to update +// |state|. You should not use this function unless you are implementing a +// derivative of SHA-256. +OPENSSL_EXPORT void SHA256_TransformBlocks(uint32_t state[8], + const uint8_t *data, + size_t num_blocks); + + +// SHA-384. + +// SHA384_CBLOCK is the block size of SHA-384. +#define SHA384_CBLOCK 128 + +// SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. +#define SHA384_DIGEST_LENGTH 48 + +// SHA384_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha); + +// SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); + +// SHA384_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA384 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, + uint8_t out[SHA384_DIGEST_LENGTH]); + + +// SHA-512. + +// SHA512_CBLOCK is the block size of SHA-512. +#define SHA512_CBLOCK 128 + +// SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. +#define SHA512_DIGEST_LENGTH 64 + +// SHA512_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha); + +// SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); + +// SHA512_Final adds the final padding to |sha| and writes the resulting digest +// to |out|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. It +// returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA512 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, + uint8_t out[SHA512_DIGEST_LENGTH]); + +// SHA512_Transform is a low-level function that performs a single, SHA-512 +// block transformation using the state from |sha| and |SHA512_CBLOCK| bytes +// from |block|. +OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, + const uint8_t block[SHA512_CBLOCK]); + + +// SHA-512-256 +// +// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6 + +#define SHA512_256_DIGEST_LENGTH 32 + +// SHA512_256_Init initialises |sha| and returns 1. +OPENSSL_EXPORT int SHA512_256_Init(SHA512_CTX *sha); + +// SHA512_256_Update adds |len| bytes from |data| to |sha| and returns 1. +OPENSSL_EXPORT int SHA512_256_Update(SHA512_CTX *sha, const void *data, + size_t len); + +// SHA512_256_Final adds the final padding to |sha| and writes the resulting +// digest to |out|, which must have at least |SHA512_256_DIGEST_LENGTH| bytes of +// space. It returns one on success and zero on programmer error. +OPENSSL_EXPORT int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], + SHA512_CTX *sha); + +// SHA512_256 writes the digest of |len| bytes from |data| to |out| and returns +// |out|. There must be at least |SHA512_256_DIGEST_LENGTH| bytes of space in +// |out|. +OPENSSL_EXPORT uint8_t *SHA512_256(const uint8_t *data, size_t len, + uint8_t out[SHA512_256_DIGEST_LENGTH]); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_SHA2_H diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_x509.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_x509.h index 42f385cab..21cba29e1 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_x509.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL_x509.h @@ -34,7 +34,7 @@ #include "CCryptoBoringSSL_pkcs7.h" #include "CCryptoBoringSSL_pool.h" #include "CCryptoBoringSSL_rsa.h" -#include "CCryptoBoringSSL_sha.h" +#include "CCryptoBoringSSL_sha2.h" #include "CCryptoBoringSSL_stack.h" #include "CCryptoBoringSSL_x509v3_errors.h" // IWYU pragma: export @@ -88,9 +88,8 @@ OPENSSL_EXPORT STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); // |i2d_X509_AUX|) are not preserved. Additionally, if |x509| is incomplete, // this function may fail. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |crl| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |crl| was mutated. OPENSSL_EXPORT X509 *X509_dup(X509 *x509); // X509_free decrements |x509|'s reference count and, if zero, releases memory @@ -101,18 +100,27 @@ OPENSSL_EXPORT void X509_free(X509 *x509); // Certificate (RFC 5280), as described in |d2i_SAMPLE|. OPENSSL_EXPORT X509 *d2i_X509(X509 **out, const uint8_t **inp, long len); -// X509_parse_from_buffer parses an X.509 structure from |buf| and returns a +// X509_parse_with_algorithms parses an X.509 structure from |buf| and returns a // fresh X509 or NULL on error. There must not be any trailing data in |buf|. -// The returned structure (if any) holds a reference to |buf| rather than -// copying parts of it as a normal |d2i_X509| call would do. +// The returned structure (if any) increment's |buf|'s reference count and +// retains a reference to it. +// +// Only the |num_algs| algorithms from |algs| will be considered when parsing +// the certificate's public key. If the certificate uses a different algorithm, +// it will still be parsed, but |X509_get0_pubkey| will return NULL. +OPENSSL_EXPORT X509 *X509_parse_with_algorithms(CRYPTO_BUFFER *buf, + const EVP_PKEY_ALG *const *algs, + size_t num_algs); + +// X509_parse_from_buffer behaves like |X509_parse_with_algorithms| but uses a +// default algorithm list. OPENSSL_EXPORT X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf); // i2d_X509 marshals |x509| as a DER-encoded X.509 Certificate (RFC 5280), as // described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |x509| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |x509| was mutated. OPENSSL_EXPORT int i2d_X509(X509 *x509, uint8_t **outp); // X509_VERSION_* are X.509 version numbers. Note the numerical values of all @@ -429,8 +437,8 @@ OPENSSL_EXPORT void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); // as equal. This function should only be used with |X509| objects that were // parsed from bytes and never mutated. // -// TODO(https://crbug.com/boringssl/407): This function is const, but it is not -// always thread-safe, notably if |a| and |b| were mutated. +// TODO(crbug.com/42290269): This function is const, but it is not always +// thread-safe, notably if |a| and |b| were mutated. OPENSSL_EXPORT int X509_cmp(const X509 *a, const X509 *b); @@ -564,7 +572,7 @@ OPENSSL_EXPORT int X509_set1_signature_value(X509 *x509, const uint8_t *sig, // ASN.1 element. Directly embedding the output in a larger ASN.1 structure will // not behave correctly. // -// TODO(crbug.com/boringssl/407): |x509| should be const. +// TODO(crbug.com/42290269): |x509| should be const. OPENSSL_EXPORT int i2d_X509_AUX(X509 *x509, uint8_t **outp); // d2i_X509_AUX parses up to |length| bytes from |*inp| as a DER-encoded X.509 @@ -675,9 +683,8 @@ OPENSSL_EXPORT int X509_CRL_up_ref(X509_CRL *crl); // function works by serializing the structure, so if |crl| is incomplete, it // may fail. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |crl| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |crl| was mutated. OPENSSL_EXPORT X509_CRL *X509_CRL_dup(X509_CRL *crl); // X509_CRL_free decrements |crl|'s reference count and, if zero, releases @@ -692,9 +699,8 @@ OPENSSL_EXPORT X509_CRL *d2i_X509_CRL(X509_CRL **out, const uint8_t **inp, // i2d_X509_CRL marshals |crl| as a X.509 CertificateList (RFC 5280), as // described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |crl| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |crl| was mutated. OPENSSL_EXPORT int i2d_X509_CRL(X509_CRL *crl, uint8_t **outp); // X509_CRL_match compares |a| and |b| and returns zero if they are equal, a @@ -1068,9 +1074,8 @@ OPENSSL_EXPORT int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, // function works by serializing the structure, so if |req| is incomplete, it // may fail. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |req| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |req| was mutated. OPENSSL_EXPORT X509_REQ *X509_REQ_dup(X509_REQ *req); // X509_REQ_free releases memory associated with |req|. @@ -1084,9 +1089,8 @@ OPENSSL_EXPORT X509_REQ *d2i_X509_REQ(X509_REQ **out, const uint8_t **inp, // i2d_X509_REQ marshals |req| as a CertificateRequest (RFC 2986), as described // in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |req| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |req| was mutated. OPENSSL_EXPORT int i2d_X509_REQ(X509_REQ *req, uint8_t **outp); // X509_REQ_VERSION_1 is the version constant for |X509_REQ| objects. No other @@ -1352,24 +1356,22 @@ OPENSSL_EXPORT X509_NAME *d2i_X509_NAME(X509_NAME **out, const uint8_t **inp, // i2d_X509_NAME marshals |in| as a DER-encoded X.509 Name (RFC 5280), as // described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |in| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |in| was mutated. OPENSSL_EXPORT int i2d_X509_NAME(X509_NAME *in, uint8_t **outp); // X509_NAME_dup returns a newly-allocated copy of |name|, or NULL on error. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |name| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |name| was mutated. OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *name); // X509_NAME_cmp compares |a| and |b|'s canonicalized forms. It returns zero if // they are equal, one if |a| sorts after |b|, -1 if |b| sorts after |a|, and -2 // on error. // -// TODO(https://crbug.com/boringssl/407): This function is const, but it is not -// always thread-safe, notably if |name| was mutated. +// TODO(crbug.com/42290269): This function is const, but it is not always +// thread-safe, notably if |name| was mutated. // // TODO(https://crbug.com/boringssl/355): The -2 return is very inconvenient to // pass to a sorting function. Can we make this infallible? In the meantime, @@ -1386,17 +1388,15 @@ OPENSSL_EXPORT int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); // Avoid this function and prefer |i2d_X509_NAME|. It is one of the reasons // |X509_NAME| functions, including this one, are not consistently thread-safe // or const-correct. Depending on the resolution of -// https://crbug.com/boringssl/407, this function may be removed or cause poor -// performance. +// crbug.com/42290269, this function may be removed or cause poor performance. OPENSSL_EXPORT int X509_NAME_get0_der(X509_NAME *name, const uint8_t **out_der, size_t *out_der_len); // X509_NAME_set makes a copy of |name|. On success, it frees |*xn|, sets |*xn| // to the copy, and returns one. Otherwise, it returns zero. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |name| was -// mutated. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |name| was mutated. OPENSSL_EXPORT int X509_NAME_set(X509_NAME **xn, X509_NAME *name); // X509_NAME_entry_count returns the number of entries in |name|. @@ -2093,18 +2093,18 @@ OPENSSL_EXPORT GENERAL_NAME *d2i_GENERAL_NAME(GENERAL_NAME **out, // i2d_GENERAL_NAME marshals |in| as a DER-encoded X.509 GeneralName (RFC 5280), // as described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |in| is an -// directoryName and the |X509_NAME| has been modified. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |in| is an directoryName and +// the |X509_NAME| has been modified. OPENSSL_EXPORT int i2d_GENERAL_NAME(GENERAL_NAME *in, uint8_t **outp); // GENERAL_NAME_dup returns a newly-allocated copy of |gen|, or NULL on error. // This function works by serializing the structure, so it will fail if |gen| is // empty. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if |gen| is an -// directoryName and the |X509_NAME| has been modified. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if |gen| is an directoryName and +// the |X509_NAME| has been modified. OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *gen); // GENERAL_NAMES_new returns a new, empty |GENERAL_NAMES|, or NULL on error. @@ -2121,9 +2121,9 @@ OPENSSL_EXPORT GENERAL_NAMES *d2i_GENERAL_NAMES(GENERAL_NAMES **out, // i2d_GENERAL_NAMES marshals |in| as a DER-encoded SEQUENCE OF GeneralName, as // described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): This function should be const and -// thread-safe but is currently neither in some cases, notably if some element -// of |in| is an directoryName and the |X509_NAME| has been modified. +// TODO(crbug.com/42290269): This function should be const and thread-safe but +// is currently neither in some cases, notably if some element of |in| is an +// directoryName and the |X509_NAME| has been modified. OPENSSL_EXPORT int i2d_GENERAL_NAMES(GENERAL_NAMES *in, uint8_t **outp); // OTHERNAME_new returns a new, empty |OTHERNAME|, or NULL on error. @@ -2229,8 +2229,8 @@ OPENSSL_EXPORT AUTHORITY_KEYID *d2i_AUTHORITY_KEYID(AUTHORITY_KEYID **out, // i2d_AUTHORITY_KEYID marshals |akid| as a DER-encoded AuthorityKeyIdentifier // (RFC 5280), as described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): |akid| is not const because it -// contains an |X509_NAME|. +// TODO(crbug.com/42290269): |akid| is not const because it contains an +// |X509_NAME|. OPENSSL_EXPORT int i2d_AUTHORITY_KEYID(AUTHORITY_KEYID *akid, uint8_t **outp); @@ -2322,8 +2322,8 @@ OPENSSL_EXPORT AUTHORITY_INFO_ACCESS *d2i_AUTHORITY_INFO_ACCESS( // i2d_AUTHORITY_INFO_ACCESS marshals |aia| as a DER-encoded // AuthorityInfoAccessSyntax (RFC 5280), as described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): |aia| is not const because it -// contains an |X509_NAME|. +// TODO(crbug.com/42290269): |aia| is not const because it contains an +// |X509_NAME|. OPENSSL_EXPORT int i2d_AUTHORITY_INFO_ACCESS(AUTHORITY_INFO_ACCESS *aia, uint8_t **outp); @@ -2397,8 +2397,8 @@ OPENSSL_EXPORT CRL_DIST_POINTS *d2i_CRL_DIST_POINTS(CRL_DIST_POINTS **out, // i2d_CRL_DIST_POINTS marshals |crldp| as a DER-encoded CRLDistributionPoints // (RFC 5280), as described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): |crldp| is not const because it -// contains an |X509_NAME|. +// TODO(crbug.com/42290269): |crldp| is not const because it contains an +// |X509_NAME|. OPENSSL_EXPORT int i2d_CRL_DIST_POINTS(CRL_DIST_POINTS *crldp, uint8_t **outp); // A ISSUING_DIST_POINT_st, aka |ISSUING_DIST_POINT|, represents a @@ -2431,8 +2431,8 @@ OPENSSL_EXPORT ISSUING_DIST_POINT *d2i_ISSUING_DIST_POINT( // i2d_ISSUING_DIST_POINT marshals |idp| as a DER-encoded // IssuingDistributionPoint (RFC 5280), as described in |i2d_SAMPLE|. // -// TODO(https://crbug.com/boringssl/407): |idp| is not const because it -// contains an |X509_NAME|. +// TODO(crbug.com/42290269): |idp| is not const because it contains an +// |X509_NAME|. OPENSSL_EXPORT int i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT *idp, uint8_t **outp); @@ -2597,6 +2597,10 @@ OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_new(void); // it may fail. OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_dup(const X509_ALGOR *alg); +// X509_ALGOR_copy sets |dst| to a copy of the contents of |src|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int X509_ALGOR_copy(X509_ALGOR *dst, const X509_ALGOR *src); + // X509_ALGOR_free releases memory associated with |alg|. OPENSSL_EXPORT void X509_ALGOR_free(X509_ALGOR *alg); @@ -3705,9 +3709,8 @@ OPENSSL_EXPORT int X509_load_cert_crl_file(X509_LOOKUP *lookup, // there will be hash collisions. It also depends on an OpenSSL-specific // canonicalization process. // -// TODO(https://crbug.com/boringssl/407): This should be const and thread-safe -// but currently is neither, notably if |name| was modified from its parsed -// value. +// TODO(crbug.com/42290269): This should be const and thread-safe but currently +// is neither, notably if |name| was modified from its parsed value. OPENSSL_EXPORT uint32_t X509_NAME_hash(X509_NAME *name); // X509_NAME_hash_old returns a hash of |name|, or zero on error. This is the @@ -3718,9 +3721,8 @@ OPENSSL_EXPORT uint32_t X509_NAME_hash(X509_NAME *name); // not suitable for general-purpose X.509 name processing. It is very short, so // there will be hash collisions. // -// TODO(https://crbug.com/boringssl/407): This should be const and thread-safe -// but currently is neither, notably if |name| was modified from its parsed -// value. +// TODO(crbug.com/42290269): This should be const and thread-safe but currently +// is neither, notably if |name| was modified from its parsed value. OPENSSL_EXPORT uint32_t X509_NAME_hash_old(X509_NAME *name); // X509_STORE_set_default_paths configures |store| to read from some "default" @@ -4439,6 +4441,9 @@ OPENSSL_EXPORT int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); // not suitable for general-purpose X.509 name processing. It is very short, so // there will be hash collisions. It also depends on an OpenSSL-specific // canonicalization process. +// +// TODO(crbug.com/42290269): This should be const and thread-safe but currently +// is neither, notably if |x509| was modified from its parsed value. OPENSSL_EXPORT uint32_t X509_issuer_name_hash(X509 *x509); // X509_subject_name_hash returns the hash of |x509|'s subject name with @@ -4448,6 +4453,9 @@ OPENSSL_EXPORT uint32_t X509_issuer_name_hash(X509 *x509); // not suitable for general-purpose X.509 name processing. It is very short, so // there will be hash collisions. It also depends on an OpenSSL-specific // canonicalization process. +// +// TODO(crbug.com/42290269): This should be const and thread-safe but currently +// is neither, notably if |x509| was modified from its parsed value. OPENSSL_EXPORT uint32_t X509_subject_name_hash(X509 *x509); // X509_issuer_name_hash_old returns the hash of |x509|'s issuer name with @@ -4456,6 +4464,9 @@ OPENSSL_EXPORT uint32_t X509_subject_name_hash(X509 *x509); // This hash is specific to the |X509_LOOKUP_add_dir| filesystem format and is // not suitable for general-purpose X.509 name processing. It is very short, so // there will be hash collisions. +// +// TODO(crbug.com/42290269): This should be const and thread-safe but currently +// is neither, notably if |x509| was modified from its parsed value. OPENSSL_EXPORT uint32_t X509_issuer_name_hash_old(X509 *x509); // X509_subject_name_hash_old returns the hash of |x509|'s usjbect name with @@ -4464,6 +4475,9 @@ OPENSSL_EXPORT uint32_t X509_issuer_name_hash_old(X509 *x509); // This hash is specific to the |X509_LOOKUP_add_dir| filesystem format and is // not suitable for general-purpose X.509 name processing. It is very short, so // there will be hash collisions. +// +// TODO(crbug.com/42290269): This should be const and thread-safe but currently +// is neither, notably if |x509| was modified from its parsed value. OPENSSL_EXPORT uint32_t X509_subject_name_hash_old(X509 *x509); @@ -4535,6 +4549,9 @@ OPENSSL_EXPORT int ASN1_item_verify(const ASN1_ITEM *it, // |md|, or |pkey|'s default if NULL. Other signing parameters use |pkey|'s // defaults. To customize them, use |ASN1_item_sign_ctx|. // +// |algor1| and |algor2| may point into part of |asn| and will be updated before +// |asn| is serialized. +// // WARNING: |data| must be a pointer with the same type as |it|'s corresponding // C type. Using the wrong type is a potentially exploitable memory error. OPENSSL_EXPORT int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, @@ -4550,6 +4567,9 @@ OPENSSL_EXPORT int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, // On success or failure, this function mutates |ctx| and resets it to the empty // state. Caller should not rely on its contents after the function returns. // +// |algor1| and |algor2| may point into part of |asn| and will be updated before +// |asn| is serialized. +// // WARNING: |data| must be a pointer with the same type as |it|'s corresponding // C type. Using the wrong type is a potentially exploitable memory error. OPENSSL_EXPORT int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, @@ -4582,7 +4602,7 @@ OPENSSL_EXPORT int X509_supported_extension(const X509_EXTENSION *ex); // This function returning one does not indicate that |x509| is trusted, only // that it is eligible to be a CA. // -// TODO(crbug.com/boringssl/407): |x509| should be const. +// TODO(crbug.com/42290269): |x509| should be const. OPENSSL_EXPORT int X509_check_ca(X509 *x509); // X509_check_issued checks if |issuer| and |subject|'s name, authority key @@ -4593,13 +4613,13 @@ OPENSSL_EXPORT int X509_check_ca(X509 *x509); // intended to prune the set of possible issuer certificates during // path-building. // -// TODO(crbug.com/boringssl/407): Both parameters should be const. +// TODO(crbug.com/42290269): Both parameters should be const. OPENSSL_EXPORT int X509_check_issued(X509 *issuer, X509 *subject); // NAME_CONSTRAINTS_check checks if |x509| satisfies name constraints in |nc|. // It returns |X509_V_OK| on success and some |X509_V_ERR_*| constant on error. // -// TODO(crbug.com/boringssl/407): Both parameters should be const. +// TODO(crbug.com/42290269): Both parameters should be const. OPENSSL_EXPORT int NAME_CONSTRAINTS_check(X509 *x509, NAME_CONSTRAINTS *nc); // X509_check_host checks if |x509| matches the DNS name |chk|. It returns one @@ -4679,7 +4699,7 @@ OPENSSL_EXPORT int X509_check_ip_asc(const X509 *x509, const char *ipasc, // This function only searches for trusted issuers. It does not consider // untrusted intermediates passed in to |X509_STORE_CTX_init|. // -// TODO(crbug.com/boringssl/407): |x509| should be const. +// TODO(crbug.com/42290269): |x509| should be const. OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **out_issuer, X509_STORE_CTX *ctx, X509 *x509); @@ -4713,7 +4733,7 @@ OPENSSL_EXPORT int X509_check_trust(X509 *x509, int id, int flags); // NULL on error. The caller must release the result with |sk_X509_pop_free| and // |X509_free| when done. // -// TODO(crbug.com/boringssl/407): |name| should be const. +// TODO(crbug.com/42290269): |name| should be const. OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *name); @@ -4722,7 +4742,7 @@ OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, // The caller must release the result with |sk_X509_CRL_pop_free| and // |X509_CRL_free| when done. // -// TODO(crbug.com/boringssl/407): |name| should be const. +// TODO(crbug.com/42290269): |name| should be const. OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *name); @@ -4740,7 +4760,7 @@ OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, // case, this function returns an arbitrary match. Use // |X509_STORE_CTX_get1_certs| or |X509_STORE_CTX_get1_crls| instead. // -// TODO(crbug.com/boringssl/407): |name| should be const. +// TODO(crbug.com/42290269): |name| should be const. OPENSSL_EXPORT int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *ctx, int type, X509_NAME *name, X509_OBJECT *ret); diff --git a/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc b/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc index cf0a13e6f..5368abb76 100644 --- a/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc +++ b/Sources/CCryptoBoringSSL/include/boringssl_prefix_symbols_nasm.inc @@ -162,8 +162,12 @@ %xdefine _ASN1_item_sign_ctx _ %+ BORINGSSL_PREFIX %+ _ASN1_item_sign_ctx %xdefine _ASN1_item_unpack _ %+ BORINGSSL_PREFIX %+ _ASN1_item_unpack %xdefine _ASN1_item_verify _ %+ BORINGSSL_PREFIX %+ _ASN1_item_verify +%xdefine _asn1_marshal_any _ %+ BORINGSSL_PREFIX %+ _asn1_marshal_any %xdefine _asn1_marshal_bit_string _ %+ BORINGSSL_PREFIX %+ _asn1_marshal_bit_string %xdefine _asn1_marshal_integer _ %+ BORINGSSL_PREFIX %+ _asn1_marshal_integer +%xdefine _asn1_marshal_object _ %+ BORINGSSL_PREFIX %+ _asn1_marshal_object +%xdefine _asn1_marshal_octet_string _ %+ BORINGSSL_PREFIX %+ _asn1_marshal_octet_string +%xdefine _asn1_marshal_time _ %+ BORINGSSL_PREFIX %+ _asn1_marshal_time %xdefine _ASN1_mbstring_copy _ %+ BORINGSSL_PREFIX %+ _ASN1_mbstring_copy %xdefine _ASN1_mbstring_ncopy _ %+ BORINGSSL_PREFIX %+ _ASN1_mbstring_ncopy %xdefine _ASN1_NULL_free _ %+ BORINGSSL_PREFIX %+ _ASN1_NULL_free @@ -180,6 +184,20 @@ %xdefine _ASN1_OCTET_STRING_it _ %+ BORINGSSL_PREFIX %+ _ASN1_OCTET_STRING_it %xdefine _ASN1_OCTET_STRING_new _ %+ BORINGSSL_PREFIX %+ _ASN1_OCTET_STRING_new %xdefine _ASN1_OCTET_STRING_set _ %+ BORINGSSL_PREFIX %+ _ASN1_OCTET_STRING_set +%xdefine _asn1_parse_any _ %+ BORINGSSL_PREFIX %+ _asn1_parse_any +%xdefine _asn1_parse_any_as_string _ %+ BORINGSSL_PREFIX %+ _asn1_parse_any_as_string +%xdefine _asn1_parse_bit_string _ %+ BORINGSSL_PREFIX %+ _asn1_parse_bit_string +%xdefine _asn1_parse_bit_string_with_bad_length _ %+ BORINGSSL_PREFIX %+ _asn1_parse_bit_string_with_bad_length +%xdefine _asn1_parse_bmp_string _ %+ BORINGSSL_PREFIX %+ _asn1_parse_bmp_string +%xdefine _asn1_parse_enumerated _ %+ BORINGSSL_PREFIX %+ _asn1_parse_enumerated +%xdefine _asn1_parse_generalized_time _ %+ BORINGSSL_PREFIX %+ _asn1_parse_generalized_time +%xdefine _asn1_parse_integer _ %+ BORINGSSL_PREFIX %+ _asn1_parse_integer +%xdefine _asn1_parse_object _ %+ BORINGSSL_PREFIX %+ _asn1_parse_object +%xdefine _asn1_parse_octet_string _ %+ BORINGSSL_PREFIX %+ _asn1_parse_octet_string +%xdefine _asn1_parse_time _ %+ BORINGSSL_PREFIX %+ _asn1_parse_time +%xdefine _asn1_parse_universal_string _ %+ BORINGSSL_PREFIX %+ _asn1_parse_universal_string +%xdefine _asn1_parse_utc_time _ %+ BORINGSSL_PREFIX %+ _asn1_parse_utc_time +%xdefine _asn1_parse_utf8_string _ %+ BORINGSSL_PREFIX %+ _asn1_parse_utf8_string %xdefine _ASN1_primitive_free _ %+ BORINGSSL_PREFIX %+ _ASN1_primitive_free %xdefine _ASN1_PRINTABLESTRING_free _ %+ BORINGSSL_PREFIX %+ _ASN1_PRINTABLESTRING_free %xdefine _ASN1_PRINTABLESTRING_it _ %+ BORINGSSL_PREFIX %+ _ASN1_PRINTABLESTRING_it @@ -190,6 +208,7 @@ %xdefine _asn1_refcount_set_one _ %+ BORINGSSL_PREFIX %+ _asn1_refcount_set_one %xdefine _ASN1_SEQUENCE_it _ %+ BORINGSSL_PREFIX %+ _ASN1_SEQUENCE_it %xdefine _asn1_set_choice_selector _ %+ BORINGSSL_PREFIX %+ _asn1_set_choice_selector +%xdefine _asn1_string_cleanup _ %+ BORINGSSL_PREFIX %+ _asn1_string_cleanup %xdefine _ASN1_STRING_cmp _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_cmp %xdefine _ASN1_STRING_copy _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_copy %xdefine _ASN1_STRING_data _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_data @@ -197,6 +216,7 @@ %xdefine _ASN1_STRING_free _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_free %xdefine _ASN1_STRING_get_default_mask _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_get_default_mask %xdefine _ASN1_STRING_get0_data _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_get0_data +%xdefine _asn1_string_init _ %+ BORINGSSL_PREFIX %+ _asn1_string_init %xdefine _ASN1_STRING_length _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_length %xdefine _ASN1_STRING_new _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_new %xdefine _ASN1_STRING_print _ %+ BORINGSSL_PREFIX %+ _ASN1_STRING_print @@ -277,6 +297,26 @@ %xdefine _bcm_as_approved_status _ %+ BORINGSSL_PREFIX %+ _bcm_as_approved_status %xdefine _bcm_as_not_approved_status _ %+ BORINGSSL_PREFIX %+ _bcm_as_not_approved_status %xdefine _BCM_fips_186_2_prf _ %+ BORINGSSL_PREFIX %+ _BCM_fips_186_2_prf +%xdefine _BCM_mldsa44_check_key_fips _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_check_key_fips +%xdefine _BCM_mldsa44_generate_key _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key +%xdefine _BCM_mldsa44_generate_key_external_entropy _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key_external_entropy +%xdefine _BCM_mldsa44_generate_key_external_entropy_fips _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key_external_entropy_fips +%xdefine _BCM_mldsa44_generate_key_fips _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key_fips +%xdefine _BCM_mldsa44_marshal_private_key _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_marshal_private_key +%xdefine _BCM_mldsa44_marshal_public_key _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_marshal_public_key +%xdefine _BCM_mldsa44_parse_private_key _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_parse_private_key +%xdefine _BCM_mldsa44_parse_public_key _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_parse_public_key +%xdefine _BCM_mldsa44_prehash_finalize _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_prehash_finalize +%xdefine _BCM_mldsa44_prehash_init _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_prehash_init +%xdefine _BCM_mldsa44_prehash_update _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_prehash_update +%xdefine _BCM_mldsa44_private_key_from_seed _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_private_key_from_seed +%xdefine _BCM_mldsa44_private_key_from_seed_fips _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_private_key_from_seed_fips +%xdefine _BCM_mldsa44_public_from_private _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_public_from_private +%xdefine _BCM_mldsa44_sign _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_sign +%xdefine _BCM_mldsa44_sign_internal _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_sign_internal +%xdefine _BCM_mldsa44_sign_message_representative _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_sign_message_representative +%xdefine _BCM_mldsa44_verify _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_verify +%xdefine _BCM_mldsa44_verify_internal _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa44_verify_internal %xdefine _BCM_mldsa65_check_key_fips _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa65_check_key_fips %xdefine _BCM_mldsa65_generate_key _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa65_generate_key %xdefine _BCM_mldsa65_generate_key_external_entropy _ %+ BORINGSSL_PREFIX %+ _BCM_mldsa65_generate_key_external_entropy @@ -627,9 +667,9 @@ %xdefine _bn_mul_comba4 _ %+ BORINGSSL_PREFIX %+ _bn_mul_comba4 %xdefine _bn_mul_comba8 _ %+ BORINGSSL_PREFIX %+ _bn_mul_comba8 %xdefine _bn_mul_consttime _ %+ BORINGSSL_PREFIX %+ _bn_mul_consttime -%xdefine _bn_mul_mont _ %+ BORINGSSL_PREFIX %+ _bn_mul_mont %xdefine _bn_mul_mont_gather5_nohw _ %+ BORINGSSL_PREFIX %+ _bn_mul_mont_gather5_nohw %xdefine _bn_mul_mont_nohw _ %+ BORINGSSL_PREFIX %+ _bn_mul_mont_nohw +%xdefine _bn_mul_mont_words _ %+ BORINGSSL_PREFIX %+ _bn_mul_mont_words %xdefine _bn_mul_small _ %+ BORINGSSL_PREFIX %+ _bn_mul_small %xdefine _BN_mul_word _ %+ BORINGSSL_PREFIX %+ _BN_mul_word %xdefine _bn_mul_words _ %+ BORINGSSL_PREFIX %+ _bn_mul_words @@ -877,6 +917,7 @@ %xdefine _CMS_sign _ %+ BORINGSSL_PREFIX %+ _CMS_sign %xdefine _CONF_modules_free _ %+ BORINGSSL_PREFIX %+ _CONF_modules_free %xdefine _CONF_modules_load_file _ %+ BORINGSSL_PREFIX %+ _CONF_modules_load_file +%xdefine _CONF_modules_unload _ %+ BORINGSSL_PREFIX %+ _CONF_modules_unload %xdefine _CONF_parse_list _ %+ BORINGSSL_PREFIX %+ _CONF_parse_list %xdefine _CONF_VALUE_new _ %+ BORINGSSL_PREFIX %+ _CONF_VALUE_new %xdefine _CRL_DIST_POINTS_free _ %+ BORINGSSL_PREFIX %+ _CRL_DIST_POINTS_free @@ -1011,7 +1052,9 @@ %xdefine _CTR_DRBG_generate _ %+ BORINGSSL_PREFIX %+ _CTR_DRBG_generate %xdefine _CTR_DRBG_init _ %+ BORINGSSL_PREFIX %+ _CTR_DRBG_init %xdefine _CTR_DRBG_new _ %+ BORINGSSL_PREFIX %+ _CTR_DRBG_new +%xdefine _CTR_DRBG_new_df _ %+ BORINGSSL_PREFIX %+ _CTR_DRBG_new_df %xdefine _CTR_DRBG_reseed _ %+ BORINGSSL_PREFIX %+ _CTR_DRBG_reseed +%xdefine _CTR_DRBG_reseed_ex _ %+ BORINGSSL_PREFIX %+ _CTR_DRBG_reseed_ex %xdefine _d2i_ASN1_BIT_STRING _ %+ BORINGSSL_PREFIX %+ _d2i_ASN1_BIT_STRING %xdefine _d2i_ASN1_BMPSTRING _ %+ BORINGSSL_PREFIX %+ _d2i_ASN1_BMPSTRING %xdefine _d2i_ASN1_BOOLEAN _ %+ BORINGSSL_PREFIX %+ _d2i_ASN1_BOOLEAN @@ -1102,7 +1145,6 @@ %xdefine _d2i_X509_AUX _ %+ BORINGSSL_PREFIX %+ _d2i_X509_AUX %xdefine _d2i_X509_bio _ %+ BORINGSSL_PREFIX %+ _d2i_X509_bio %xdefine _d2i_X509_CERT_AUX _ %+ BORINGSSL_PREFIX %+ _d2i_X509_CERT_AUX -%xdefine _d2i_X509_CINF _ %+ BORINGSSL_PREFIX %+ _d2i_X509_CINF %xdefine _d2i_X509_CRL _ %+ BORINGSSL_PREFIX %+ _d2i_X509_CRL %xdefine _d2i_X509_CRL_bio _ %+ BORINGSSL_PREFIX %+ _d2i_X509_CRL_bio %xdefine _d2i_X509_CRL_fp _ %+ BORINGSSL_PREFIX %+ _d2i_X509_CRL_fp @@ -1118,7 +1160,6 @@ %xdefine _d2i_X509_REQ_INFO _ %+ BORINGSSL_PREFIX %+ _d2i_X509_REQ_INFO %xdefine _d2i_X509_REVOKED _ %+ BORINGSSL_PREFIX %+ _d2i_X509_REVOKED %xdefine _d2i_X509_SIG _ %+ BORINGSSL_PREFIX %+ _d2i_X509_SIG -%xdefine _d2i_X509_VAL _ %+ BORINGSSL_PREFIX %+ _d2i_X509_VAL %xdefine _DES_decrypt3 _ %+ BORINGSSL_PREFIX %+ _DES_decrypt3 %xdefine _DES_ecb_encrypt _ %+ BORINGSSL_PREFIX %+ _DES_ecb_encrypt %xdefine _DES_ecb_encrypt_ex _ %+ BORINGSSL_PREFIX %+ _DES_ecb_encrypt_ex @@ -1326,8 +1367,11 @@ %xdefine _EC_KEY_new_method _ %+ BORINGSSL_PREFIX %+ _EC_KEY_new_method %xdefine _EC_KEY_oct2key _ %+ BORINGSSL_PREFIX %+ _EC_KEY_oct2key %xdefine _EC_KEY_oct2priv _ %+ BORINGSSL_PREFIX %+ _EC_KEY_oct2priv +%xdefine _ec_key_parse_curve_name _ %+ BORINGSSL_PREFIX %+ _ec_key_parse_curve_name %xdefine _EC_KEY_parse_curve_name _ %+ BORINGSSL_PREFIX %+ _EC_KEY_parse_curve_name +%xdefine _ec_key_parse_parameters _ %+ BORINGSSL_PREFIX %+ _ec_key_parse_parameters %xdefine _EC_KEY_parse_parameters _ %+ BORINGSSL_PREFIX %+ _EC_KEY_parse_parameters +%xdefine _ec_key_parse_private_key _ %+ BORINGSSL_PREFIX %+ _ec_key_parse_private_key %xdefine _EC_KEY_parse_private_key _ %+ BORINGSSL_PREFIX %+ _EC_KEY_parse_private_key %xdefine _EC_KEY_priv2buf _ %+ BORINGSSL_PREFIX %+ _EC_KEY_priv2buf %xdefine _EC_KEY_priv2oct _ %+ BORINGSSL_PREFIX %+ _EC_KEY_priv2oct @@ -1462,6 +1506,7 @@ %xdefine _ED25519_verify _ %+ BORINGSSL_PREFIX %+ _ED25519_verify %xdefine _EDIPARTYNAME_free _ %+ BORINGSSL_PREFIX %+ _EDIPARTYNAME_free %xdefine _EDIPARTYNAME_new _ %+ BORINGSSL_PREFIX %+ _EDIPARTYNAME_new +%xdefine _ENGINE_cleanup _ %+ BORINGSSL_PREFIX %+ _ENGINE_cleanup %xdefine _ENGINE_free _ %+ BORINGSSL_PREFIX %+ _ENGINE_free %xdefine _ENGINE_get_ECDSA_method _ %+ BORINGSSL_PREFIX %+ _ENGINE_get_ECDSA_method %xdefine _ENGINE_get_RSA_method _ %+ BORINGSSL_PREFIX %+ _ENGINE_get_RSA_method @@ -1474,6 +1519,7 @@ %xdefine _ERR_add_error_dataf _ %+ BORINGSSL_PREFIX %+ _ERR_add_error_dataf %xdefine _ERR_clear_error _ %+ BORINGSSL_PREFIX %+ _ERR_clear_error %xdefine _ERR_clear_system_error _ %+ BORINGSSL_PREFIX %+ _ERR_clear_system_error +%xdefine _ERR_equals _ %+ BORINGSSL_PREFIX %+ _ERR_equals %xdefine _ERR_error_string _ %+ BORINGSSL_PREFIX %+ _ERR_error_string %xdefine _ERR_error_string_n _ %+ BORINGSSL_PREFIX %+ _ERR_error_string_n %xdefine _ERR_free_strings _ %+ BORINGSSL_PREFIX %+ _ERR_free_strings @@ -1700,6 +1746,7 @@ %xdefine _EVP_HPKE_KEY_zero _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_zero %xdefine _EVP_hpke_p256_hkdf_sha256 _ %+ BORINGSSL_PREFIX %+ _EVP_hpke_p256_hkdf_sha256 %xdefine _EVP_hpke_x25519_hkdf_sha256 _ %+ BORINGSSL_PREFIX %+ _EVP_hpke_x25519_hkdf_sha256 +%xdefine _EVP_hpke_xwing _ %+ BORINGSSL_PREFIX %+ _EVP_hpke_xwing %xdefine _EVP_marshal_digest_algorithm _ %+ BORINGSSL_PREFIX %+ _EVP_marshal_digest_algorithm %xdefine _EVP_marshal_digest_algorithm_no_params _ %+ BORINGSSL_PREFIX %+ _EVP_marshal_digest_algorithm_no_params %xdefine _EVP_marshal_private_key _ %+ BORINGSSL_PREFIX %+ _EVP_marshal_private_key @@ -1731,6 +1778,7 @@ %xdefine _EVP_md5 _ %+ BORINGSSL_PREFIX %+ _EVP_md5 %xdefine _EVP_md5_sha1 _ %+ BORINGSSL_PREFIX %+ _EVP_md5_sha1 %xdefine _EVP_parse_digest_algorithm _ %+ BORINGSSL_PREFIX %+ _EVP_parse_digest_algorithm +%xdefine _EVP_parse_digest_algorithm_nid _ %+ BORINGSSL_PREFIX %+ _EVP_parse_digest_algorithm_nid %xdefine _EVP_parse_private_key _ %+ BORINGSSL_PREFIX %+ _EVP_parse_private_key %xdefine _EVP_parse_public_key _ %+ BORINGSSL_PREFIX %+ _EVP_parse_public_key %xdefine _EVP_PBE_scrypt _ %+ BORINGSSL_PREFIX %+ _EVP_PBE_scrypt @@ -1783,9 +1831,21 @@ %xdefine _EVP_PKEY_derive _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_derive %xdefine _EVP_PKEY_derive_init _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_derive_init %xdefine _EVP_PKEY_derive_set_peer _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_derive_set_peer +%xdefine _EVP_pkey_dsa _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_dsa +%xdefine _EVP_pkey_ec_p224 _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_ec_p224 +%xdefine _EVP_pkey_ec_p256 _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_ec_p256 +%xdefine _EVP_pkey_ec_p384 _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_ec_p384 +%xdefine _EVP_pkey_ec_p521 _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_ec_p521 +%xdefine _EVP_pkey_ed25519 _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_ed25519 %xdefine _EVP_PKEY_encrypt _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_encrypt %xdefine _EVP_PKEY_encrypt_init _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_encrypt_init %xdefine _EVP_PKEY_free _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_free +%xdefine _EVP_PKEY_from_private_key_info _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_from_private_key_info +%xdefine _EVP_PKEY_from_raw_private_key _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_from_raw_private_key +%xdefine _EVP_PKEY_from_raw_public_key _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_from_raw_public_key +%xdefine _EVP_PKEY_from_subject_public_key_info _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_from_subject_public_key_info +%xdefine _EVP_PKEY_get_ec_curve_nid _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_get_ec_curve_nid +%xdefine _EVP_PKEY_get_ec_point_conv_form _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_get_ec_point_conv_form %xdefine _EVP_PKEY_get_raw_private_key _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_get_raw_private_key %xdefine _EVP_PKEY_get_raw_public_key _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_get_raw_public_key %xdefine _EVP_PKEY_get0 _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_get0 @@ -1811,8 +1871,10 @@ %xdefine _EVP_PKEY_print_params _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_print_params %xdefine _EVP_PKEY_print_private _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_print_private %xdefine _EVP_PKEY_print_public _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_print_public -%xdefine _evp_pkey_set_method _ %+ BORINGSSL_PREFIX %+ _evp_pkey_set_method +%xdefine _EVP_pkey_rsa _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_rsa +%xdefine _EVP_pkey_rsa_pss_sha256 _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_rsa_pss_sha256 %xdefine _EVP_PKEY_set_type _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_set_type +%xdefine _evp_pkey_set0 _ %+ BORINGSSL_PREFIX %+ _evp_pkey_set0 %xdefine _EVP_PKEY_set1_DH _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_set1_DH %xdefine _EVP_PKEY_set1_DSA _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_set1_DSA %xdefine _EVP_PKEY_set1_EC_KEY _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_set1_EC_KEY @@ -1827,6 +1889,7 @@ %xdefine _EVP_PKEY_verify_init _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_verify_init %xdefine _EVP_PKEY_verify_recover _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_verify_recover %xdefine _EVP_PKEY_verify_recover_init _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY_verify_recover_init +%xdefine _EVP_pkey_x25519 _ %+ BORINGSSL_PREFIX %+ _EVP_pkey_x25519 %xdefine _EVP_PKEY2PKCS8 _ %+ BORINGSSL_PREFIX %+ _EVP_PKEY2PKCS8 %xdefine _EVP_rc2_40_cbc _ %+ BORINGSSL_PREFIX %+ _EVP_rc2_40_cbc %xdefine _EVP_rc2_cbc _ %+ BORINGSSL_PREFIX %+ _EVP_rc2_cbc @@ -1863,6 +1926,8 @@ %xdefine _FIPS_module_name _ %+ BORINGSSL_PREFIX %+ _FIPS_module_name %xdefine _FIPS_query_algorithm_status _ %+ BORINGSSL_PREFIX %+ _FIPS_query_algorithm_status %xdefine _FIPS_read_counter _ %+ BORINGSSL_PREFIX %+ _FIPS_read_counter +%xdefine _FIPS_service_indicator_after_call _ %+ BORINGSSL_PREFIX %+ _FIPS_service_indicator_after_call +%xdefine _FIPS_service_indicator_before_call _ %+ BORINGSSL_PREFIX %+ _FIPS_service_indicator_before_call %xdefine _FIPS_version _ %+ BORINGSSL_PREFIX %+ _FIPS_version %xdefine _gcm_ghash_avx _ %+ BORINGSSL_PREFIX %+ _gcm_ghash_avx %xdefine _gcm_ghash_clmul _ %+ BORINGSSL_PREFIX %+ _gcm_ghash_clmul @@ -2038,7 +2103,6 @@ %xdefine _i2d_X509_AUX _ %+ BORINGSSL_PREFIX %+ _i2d_X509_AUX %xdefine _i2d_X509_bio _ %+ BORINGSSL_PREFIX %+ _i2d_X509_bio %xdefine _i2d_X509_CERT_AUX _ %+ BORINGSSL_PREFIX %+ _i2d_X509_CERT_AUX -%xdefine _i2d_X509_CINF _ %+ BORINGSSL_PREFIX %+ _i2d_X509_CINF %xdefine _i2d_X509_CRL _ %+ BORINGSSL_PREFIX %+ _i2d_X509_CRL %xdefine _i2d_X509_CRL_bio _ %+ BORINGSSL_PREFIX %+ _i2d_X509_CRL_bio %xdefine _i2d_X509_CRL_fp _ %+ BORINGSSL_PREFIX %+ _i2d_X509_CRL_fp @@ -2056,7 +2120,6 @@ %xdefine _i2d_X509_REVOKED _ %+ BORINGSSL_PREFIX %+ _i2d_X509_REVOKED %xdefine _i2d_X509_SIG _ %+ BORINGSSL_PREFIX %+ _i2d_X509_SIG %xdefine _i2d_X509_tbs _ %+ BORINGSSL_PREFIX %+ _i2d_X509_tbs -%xdefine _i2d_X509_VAL _ %+ BORINGSSL_PREFIX %+ _i2d_X509_VAL %xdefine _i2o_ECPublicKey _ %+ BORINGSSL_PREFIX %+ _i2o_ECPublicKey %xdefine _i2s_ASN1_ENUMERATED _ %+ BORINGSSL_PREFIX %+ _i2s_ASN1_ENUMERATED %xdefine _i2s_ASN1_INTEGER _ %+ BORINGSSL_PREFIX %+ _i2s_ASN1_INTEGER @@ -2120,6 +2183,17 @@ %xdefine _MD5_Update _ %+ BORINGSSL_PREFIX %+ _MD5_Update %xdefine _METHOD_ref _ %+ BORINGSSL_PREFIX %+ _METHOD_ref %xdefine _METHOD_unref _ %+ BORINGSSL_PREFIX %+ _METHOD_unref +%xdefine _MLDSA44_generate_key _ %+ BORINGSSL_PREFIX %+ _MLDSA44_generate_key +%xdefine _MLDSA44_marshal_public_key _ %+ BORINGSSL_PREFIX %+ _MLDSA44_marshal_public_key +%xdefine _MLDSA44_parse_public_key _ %+ BORINGSSL_PREFIX %+ _MLDSA44_parse_public_key +%xdefine _MLDSA44_prehash_finalize _ %+ BORINGSSL_PREFIX %+ _MLDSA44_prehash_finalize +%xdefine _MLDSA44_prehash_init _ %+ BORINGSSL_PREFIX %+ _MLDSA44_prehash_init +%xdefine _MLDSA44_prehash_update _ %+ BORINGSSL_PREFIX %+ _MLDSA44_prehash_update +%xdefine _MLDSA44_private_key_from_seed _ %+ BORINGSSL_PREFIX %+ _MLDSA44_private_key_from_seed +%xdefine _MLDSA44_public_from_private _ %+ BORINGSSL_PREFIX %+ _MLDSA44_public_from_private +%xdefine _MLDSA44_sign _ %+ BORINGSSL_PREFIX %+ _MLDSA44_sign +%xdefine _MLDSA44_sign_message_representative _ %+ BORINGSSL_PREFIX %+ _MLDSA44_sign_message_representative +%xdefine _MLDSA44_verify _ %+ BORINGSSL_PREFIX %+ _MLDSA44_verify %xdefine _MLDSA65_generate_key _ %+ BORINGSSL_PREFIX %+ _MLDSA65_generate_key %xdefine _MLDSA65_marshal_public_key _ %+ BORINGSSL_PREFIX %+ _MLDSA65_marshal_public_key %xdefine _MLDSA65_parse_public_key _ %+ BORINGSSL_PREFIX %+ _MLDSA65_parse_public_key @@ -2517,6 +2591,7 @@ %xdefine _rsa_invalidate_key _ %+ BORINGSSL_PREFIX %+ _rsa_invalidate_key %xdefine _RSA_is_opaque _ %+ BORINGSSL_PREFIX %+ _RSA_is_opaque %xdefine _RSA_marshal_private_key _ %+ BORINGSSL_PREFIX %+ _RSA_marshal_private_key +%xdefine _rsa_marshal_pss_params _ %+ BORINGSSL_PREFIX %+ _rsa_marshal_pss_params %xdefine _RSA_marshal_public_key _ %+ BORINGSSL_PREFIX %+ _RSA_marshal_public_key %xdefine _RSA_new _ %+ BORINGSSL_PREFIX %+ _RSA_new %xdefine _RSA_new_method _ %+ BORINGSSL_PREFIX %+ _RSA_new_method @@ -2534,6 +2609,7 @@ %xdefine _RSA_padding_check_PKCS1_OAEP_mgf1 _ %+ BORINGSSL_PREFIX %+ _RSA_padding_check_PKCS1_OAEP_mgf1 %xdefine _RSA_padding_check_PKCS1_type_1 _ %+ BORINGSSL_PREFIX %+ _RSA_padding_check_PKCS1_type_1 %xdefine _RSA_parse_private_key _ %+ BORINGSSL_PREFIX %+ _RSA_parse_private_key +%xdefine _rsa_parse_pss_params _ %+ BORINGSSL_PREFIX %+ _rsa_parse_pss_params %xdefine _RSA_parse_public_key _ %+ BORINGSSL_PREFIX %+ _RSA_parse_public_key %xdefine _rsa_pkey_meth _ %+ BORINGSSL_PREFIX %+ _rsa_pkey_meth %xdefine _RSA_print _ %+ BORINGSSL_PREFIX %+ _RSA_print @@ -2544,8 +2620,11 @@ %xdefine _rsa_private_transform _ %+ BORINGSSL_PREFIX %+ _rsa_private_transform %xdefine _rsa_private_transform_no_self_test _ %+ BORINGSSL_PREFIX %+ _rsa_private_transform_no_self_test %xdefine _RSA_PSS_PARAMS_free _ %+ BORINGSSL_PREFIX %+ _RSA_PSS_PARAMS_free +%xdefine _rsa_pss_params_get_md _ %+ BORINGSSL_PREFIX %+ _rsa_pss_params_get_md %xdefine _RSA_PSS_PARAMS_it _ %+ BORINGSSL_PREFIX %+ _RSA_PSS_PARAMS_it %xdefine _RSA_PSS_PARAMS_new _ %+ BORINGSSL_PREFIX %+ _RSA_PSS_PARAMS_new +%xdefine _rsa_pss_sha256_asn1_meth _ %+ BORINGSSL_PREFIX %+ _rsa_pss_sha256_asn1_meth +%xdefine _rsa_pss_sha256_pkey_meth _ %+ BORINGSSL_PREFIX %+ _rsa_pss_sha256_pkey_meth %xdefine _RSA_public_decrypt _ %+ BORINGSSL_PREFIX %+ _RSA_public_decrypt %xdefine _RSA_public_encrypt _ %+ BORINGSSL_PREFIX %+ _RSA_public_encrypt %xdefine _RSA_public_key_from_bytes _ %+ BORINGSSL_PREFIX %+ _RSA_public_key_from_bytes @@ -2995,10 +3074,13 @@ %xdefine _X509_add1_ext_i2d _ %+ BORINGSSL_PREFIX %+ _X509_add1_ext_i2d %xdefine _X509_add1_reject_object _ %+ BORINGSSL_PREFIX %+ _X509_add1_reject_object %xdefine _X509_add1_trust_object _ %+ BORINGSSL_PREFIX %+ _X509_add1_trust_object +%xdefine _x509_algor_cleanup _ %+ BORINGSSL_PREFIX %+ _x509_algor_cleanup %xdefine _X509_ALGOR_cmp _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_cmp +%xdefine _X509_ALGOR_copy _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_copy %xdefine _X509_ALGOR_dup _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_dup %xdefine _X509_ALGOR_free _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_free %xdefine _X509_ALGOR_get0 _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_get0 +%xdefine _x509_algor_init _ %+ BORINGSSL_PREFIX %+ _x509_algor_init %xdefine _X509_ALGOR_it _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_it %xdefine _X509_ALGOR_new _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_new %xdefine _X509_ALGOR_set_md _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_set_md @@ -3035,9 +3117,6 @@ %xdefine _X509_check_private_key _ %+ BORINGSSL_PREFIX %+ _X509_check_private_key %xdefine _X509_check_purpose _ %+ BORINGSSL_PREFIX %+ _X509_check_purpose %xdefine _X509_check_trust _ %+ BORINGSSL_PREFIX %+ _X509_check_trust -%xdefine _X509_CINF_free _ %+ BORINGSSL_PREFIX %+ _X509_CINF_free -%xdefine _X509_CINF_it _ %+ BORINGSSL_PREFIX %+ _X509_CINF_it -%xdefine _X509_CINF_new _ %+ BORINGSSL_PREFIX %+ _X509_CINF_new %xdefine _X509_cmp _ %+ BORINGSSL_PREFIX %+ _X509_cmp %xdefine _X509_cmp_current_time _ %+ BORINGSSL_PREFIX %+ _X509_cmp_current_time %xdefine _X509_cmp_time _ %+ BORINGSSL_PREFIX %+ _X509_cmp_time @@ -3173,6 +3252,8 @@ %xdefine _X509_LOOKUP_load_file _ %+ BORINGSSL_PREFIX %+ _X509_LOOKUP_load_file %xdefine _x509_marshal_algorithm _ %+ BORINGSSL_PREFIX %+ _x509_marshal_algorithm %xdefine _x509_marshal_name _ %+ BORINGSSL_PREFIX %+ _x509_marshal_name +%xdefine _x509_marshal_public_key _ %+ BORINGSSL_PREFIX %+ _x509_marshal_public_key +%xdefine _x509_marshal_tbs_cert _ %+ BORINGSSL_PREFIX %+ _x509_marshal_tbs_cert %xdefine _X509_NAME_add_entry _ %+ BORINGSSL_PREFIX %+ _X509_NAME_add_entry %xdefine _X509_NAME_add_entry_by_NID _ %+ BORINGSSL_PREFIX %+ _X509_NAME_add_entry_by_NID %xdefine _X509_NAME_add_entry_by_OBJ _ %+ BORINGSSL_PREFIX %+ _X509_NAME_add_entry_by_OBJ @@ -3216,23 +3297,29 @@ %xdefine _X509_OBJECT_get_type _ %+ BORINGSSL_PREFIX %+ _X509_OBJECT_get_type %xdefine _X509_OBJECT_get0_X509 _ %+ BORINGSSL_PREFIX %+ _X509_OBJECT_get0_X509 %xdefine _X509_OBJECT_new _ %+ BORINGSSL_PREFIX %+ _X509_OBJECT_new +%xdefine _x509_parse_algorithm _ %+ BORINGSSL_PREFIX %+ _x509_parse_algorithm %xdefine _X509_parse_from_buffer _ %+ BORINGSSL_PREFIX %+ _X509_parse_from_buffer +%xdefine _x509_parse_public_key _ %+ BORINGSSL_PREFIX %+ _x509_parse_public_key +%xdefine _X509_parse_with_algorithms _ %+ BORINGSSL_PREFIX %+ _X509_parse_with_algorithms %xdefine _X509_policy_check _ %+ BORINGSSL_PREFIX %+ _X509_policy_check %xdefine _X509_print _ %+ BORINGSSL_PREFIX %+ _X509_print %xdefine _X509_print_ex _ %+ BORINGSSL_PREFIX %+ _X509_print_ex %xdefine _X509_print_ex_fp _ %+ BORINGSSL_PREFIX %+ _X509_print_ex_fp %xdefine _X509_print_fp _ %+ BORINGSSL_PREFIX %+ _X509_print_fp %xdefine _x509_print_rsa_pss_params _ %+ BORINGSSL_PREFIX %+ _x509_print_rsa_pss_params +%xdefine _x509_pubkey_cleanup _ %+ BORINGSSL_PREFIX %+ _x509_pubkey_cleanup %xdefine _X509_pubkey_digest _ %+ BORINGSSL_PREFIX %+ _X509_pubkey_digest %xdefine _X509_PUBKEY_free _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_free %xdefine _X509_PUBKEY_get _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_get %xdefine _X509_PUBKEY_get0 _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_get0 %xdefine _X509_PUBKEY_get0_param _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_param %xdefine _X509_PUBKEY_get0_public_key _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_public_key +%xdefine _x509_pubkey_init _ %+ BORINGSSL_PREFIX %+ _x509_pubkey_init %xdefine _X509_PUBKEY_it _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_it %xdefine _X509_PUBKEY_new _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_new %xdefine _X509_PUBKEY_set _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_set %xdefine _X509_PUBKEY_set0_param _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_set0_param +%xdefine _x509_pubkey_set1 _ %+ BORINGSSL_PREFIX %+ _x509_pubkey_set1 %xdefine _X509_PURPOSE_get_by_sname _ %+ BORINGSSL_PREFIX %+ _X509_PURPOSE_get_by_sname %xdefine _X509_PURPOSE_get_id _ %+ BORINGSSL_PREFIX %+ _X509_PURPOSE_get_id %xdefine _X509_PURPOSE_get_trust _ %+ BORINGSSL_PREFIX %+ _X509_PURPOSE_get_trust @@ -3316,6 +3403,7 @@ %xdefine _X509_SIG_new _ %+ BORINGSSL_PREFIX %+ _X509_SIG_new %xdefine _X509_sign _ %+ BORINGSSL_PREFIX %+ _X509_sign %xdefine _X509_sign_ctx _ %+ BORINGSSL_PREFIX %+ _X509_sign_ctx +%xdefine _x509_sign_to_bit_string _ %+ BORINGSSL_PREFIX %+ _x509_sign_to_bit_string %xdefine _X509_signature_dump _ %+ BORINGSSL_PREFIX %+ _X509_signature_dump %xdefine _X509_signature_print _ %+ BORINGSSL_PREFIX %+ _X509_signature_print %xdefine _X509_STORE_add_cert _ %+ BORINGSSL_PREFIX %+ _X509_STORE_add_cert @@ -3380,9 +3468,6 @@ %xdefine _X509_time_adj_ex _ %+ BORINGSSL_PREFIX %+ _X509_time_adj_ex %xdefine _X509_trust_clear _ %+ BORINGSSL_PREFIX %+ _X509_trust_clear %xdefine _X509_up_ref _ %+ BORINGSSL_PREFIX %+ _X509_up_ref -%xdefine _X509_VAL_free _ %+ BORINGSSL_PREFIX %+ _X509_VAL_free -%xdefine _X509_VAL_it _ %+ BORINGSSL_PREFIX %+ _X509_VAL_it -%xdefine _X509_VAL_new _ %+ BORINGSSL_PREFIX %+ _X509_VAL_new %xdefine _X509_verify _ %+ BORINGSSL_PREFIX %+ _X509_verify %xdefine _X509_verify_cert _ %+ BORINGSSL_PREFIX %+ _X509_verify_cert %xdefine _X509_verify_cert_error_string _ %+ BORINGSSL_PREFIX %+ _X509_verify_cert_error_string @@ -3408,6 +3493,7 @@ %xdefine _X509_VERIFY_PARAM_set1_ip _ %+ BORINGSSL_PREFIX %+ _X509_VERIFY_PARAM_set1_ip %xdefine _X509_VERIFY_PARAM_set1_ip_asc _ %+ BORINGSSL_PREFIX %+ _X509_VERIFY_PARAM_set1_ip_asc %xdefine _X509_VERIFY_PARAM_set1_policies _ %+ BORINGSSL_PREFIX %+ _X509_VERIFY_PARAM_set1_policies +%xdefine _x509_verify_signature _ %+ BORINGSSL_PREFIX %+ _x509_verify_signature %xdefine _x509v3_a2i_ipadd _ %+ BORINGSSL_PREFIX %+ _x509v3_a2i_ipadd %xdefine _X509v3_add_ext _ %+ BORINGSSL_PREFIX %+ _X509v3_add_ext %xdefine _X509V3_add_standard_extensions _ %+ BORINGSSL_PREFIX %+ _X509V3_add_standard_extensions @@ -3609,8 +3695,12 @@ %xdefine ASN1_item_sign_ctx BORINGSSL_PREFIX %+ _ASN1_item_sign_ctx %xdefine ASN1_item_unpack BORINGSSL_PREFIX %+ _ASN1_item_unpack %xdefine ASN1_item_verify BORINGSSL_PREFIX %+ _ASN1_item_verify +%xdefine asn1_marshal_any BORINGSSL_PREFIX %+ _asn1_marshal_any %xdefine asn1_marshal_bit_string BORINGSSL_PREFIX %+ _asn1_marshal_bit_string %xdefine asn1_marshal_integer BORINGSSL_PREFIX %+ _asn1_marshal_integer +%xdefine asn1_marshal_object BORINGSSL_PREFIX %+ _asn1_marshal_object +%xdefine asn1_marshal_octet_string BORINGSSL_PREFIX %+ _asn1_marshal_octet_string +%xdefine asn1_marshal_time BORINGSSL_PREFIX %+ _asn1_marshal_time %xdefine ASN1_mbstring_copy BORINGSSL_PREFIX %+ _ASN1_mbstring_copy %xdefine ASN1_mbstring_ncopy BORINGSSL_PREFIX %+ _ASN1_mbstring_ncopy %xdefine ASN1_NULL_free BORINGSSL_PREFIX %+ _ASN1_NULL_free @@ -3627,6 +3717,20 @@ %xdefine ASN1_OCTET_STRING_it BORINGSSL_PREFIX %+ _ASN1_OCTET_STRING_it %xdefine ASN1_OCTET_STRING_new BORINGSSL_PREFIX %+ _ASN1_OCTET_STRING_new %xdefine ASN1_OCTET_STRING_set BORINGSSL_PREFIX %+ _ASN1_OCTET_STRING_set +%xdefine asn1_parse_any BORINGSSL_PREFIX %+ _asn1_parse_any +%xdefine asn1_parse_any_as_string BORINGSSL_PREFIX %+ _asn1_parse_any_as_string +%xdefine asn1_parse_bit_string BORINGSSL_PREFIX %+ _asn1_parse_bit_string +%xdefine asn1_parse_bit_string_with_bad_length BORINGSSL_PREFIX %+ _asn1_parse_bit_string_with_bad_length +%xdefine asn1_parse_bmp_string BORINGSSL_PREFIX %+ _asn1_parse_bmp_string +%xdefine asn1_parse_enumerated BORINGSSL_PREFIX %+ _asn1_parse_enumerated +%xdefine asn1_parse_generalized_time BORINGSSL_PREFIX %+ _asn1_parse_generalized_time +%xdefine asn1_parse_integer BORINGSSL_PREFIX %+ _asn1_parse_integer +%xdefine asn1_parse_object BORINGSSL_PREFIX %+ _asn1_parse_object +%xdefine asn1_parse_octet_string BORINGSSL_PREFIX %+ _asn1_parse_octet_string +%xdefine asn1_parse_time BORINGSSL_PREFIX %+ _asn1_parse_time +%xdefine asn1_parse_universal_string BORINGSSL_PREFIX %+ _asn1_parse_universal_string +%xdefine asn1_parse_utc_time BORINGSSL_PREFIX %+ _asn1_parse_utc_time +%xdefine asn1_parse_utf8_string BORINGSSL_PREFIX %+ _asn1_parse_utf8_string %xdefine ASN1_primitive_free BORINGSSL_PREFIX %+ _ASN1_primitive_free %xdefine ASN1_PRINTABLESTRING_free BORINGSSL_PREFIX %+ _ASN1_PRINTABLESTRING_free %xdefine ASN1_PRINTABLESTRING_it BORINGSSL_PREFIX %+ _ASN1_PRINTABLESTRING_it @@ -3637,6 +3741,7 @@ %xdefine asn1_refcount_set_one BORINGSSL_PREFIX %+ _asn1_refcount_set_one %xdefine ASN1_SEQUENCE_it BORINGSSL_PREFIX %+ _ASN1_SEQUENCE_it %xdefine asn1_set_choice_selector BORINGSSL_PREFIX %+ _asn1_set_choice_selector +%xdefine asn1_string_cleanup BORINGSSL_PREFIX %+ _asn1_string_cleanup %xdefine ASN1_STRING_cmp BORINGSSL_PREFIX %+ _ASN1_STRING_cmp %xdefine ASN1_STRING_copy BORINGSSL_PREFIX %+ _ASN1_STRING_copy %xdefine ASN1_STRING_data BORINGSSL_PREFIX %+ _ASN1_STRING_data @@ -3644,6 +3749,7 @@ %xdefine ASN1_STRING_free BORINGSSL_PREFIX %+ _ASN1_STRING_free %xdefine ASN1_STRING_get_default_mask BORINGSSL_PREFIX %+ _ASN1_STRING_get_default_mask %xdefine ASN1_STRING_get0_data BORINGSSL_PREFIX %+ _ASN1_STRING_get0_data +%xdefine asn1_string_init BORINGSSL_PREFIX %+ _asn1_string_init %xdefine ASN1_STRING_length BORINGSSL_PREFIX %+ _ASN1_STRING_length %xdefine ASN1_STRING_new BORINGSSL_PREFIX %+ _ASN1_STRING_new %xdefine ASN1_STRING_print BORINGSSL_PREFIX %+ _ASN1_STRING_print @@ -3724,6 +3830,26 @@ %xdefine bcm_as_approved_status BORINGSSL_PREFIX %+ _bcm_as_approved_status %xdefine bcm_as_not_approved_status BORINGSSL_PREFIX %+ _bcm_as_not_approved_status %xdefine BCM_fips_186_2_prf BORINGSSL_PREFIX %+ _BCM_fips_186_2_prf +%xdefine BCM_mldsa44_check_key_fips BORINGSSL_PREFIX %+ _BCM_mldsa44_check_key_fips +%xdefine BCM_mldsa44_generate_key BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key +%xdefine BCM_mldsa44_generate_key_external_entropy BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key_external_entropy +%xdefine BCM_mldsa44_generate_key_external_entropy_fips BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key_external_entropy_fips +%xdefine BCM_mldsa44_generate_key_fips BORINGSSL_PREFIX %+ _BCM_mldsa44_generate_key_fips +%xdefine BCM_mldsa44_marshal_private_key BORINGSSL_PREFIX %+ _BCM_mldsa44_marshal_private_key +%xdefine BCM_mldsa44_marshal_public_key BORINGSSL_PREFIX %+ _BCM_mldsa44_marshal_public_key +%xdefine BCM_mldsa44_parse_private_key BORINGSSL_PREFIX %+ _BCM_mldsa44_parse_private_key +%xdefine BCM_mldsa44_parse_public_key BORINGSSL_PREFIX %+ _BCM_mldsa44_parse_public_key +%xdefine BCM_mldsa44_prehash_finalize BORINGSSL_PREFIX %+ _BCM_mldsa44_prehash_finalize +%xdefine BCM_mldsa44_prehash_init BORINGSSL_PREFIX %+ _BCM_mldsa44_prehash_init +%xdefine BCM_mldsa44_prehash_update BORINGSSL_PREFIX %+ _BCM_mldsa44_prehash_update +%xdefine BCM_mldsa44_private_key_from_seed BORINGSSL_PREFIX %+ _BCM_mldsa44_private_key_from_seed +%xdefine BCM_mldsa44_private_key_from_seed_fips BORINGSSL_PREFIX %+ _BCM_mldsa44_private_key_from_seed_fips +%xdefine BCM_mldsa44_public_from_private BORINGSSL_PREFIX %+ _BCM_mldsa44_public_from_private +%xdefine BCM_mldsa44_sign BORINGSSL_PREFIX %+ _BCM_mldsa44_sign +%xdefine BCM_mldsa44_sign_internal BORINGSSL_PREFIX %+ _BCM_mldsa44_sign_internal +%xdefine BCM_mldsa44_sign_message_representative BORINGSSL_PREFIX %+ _BCM_mldsa44_sign_message_representative +%xdefine BCM_mldsa44_verify BORINGSSL_PREFIX %+ _BCM_mldsa44_verify +%xdefine BCM_mldsa44_verify_internal BORINGSSL_PREFIX %+ _BCM_mldsa44_verify_internal %xdefine BCM_mldsa65_check_key_fips BORINGSSL_PREFIX %+ _BCM_mldsa65_check_key_fips %xdefine BCM_mldsa65_generate_key BORINGSSL_PREFIX %+ _BCM_mldsa65_generate_key %xdefine BCM_mldsa65_generate_key_external_entropy BORINGSSL_PREFIX %+ _BCM_mldsa65_generate_key_external_entropy @@ -4074,9 +4200,9 @@ %xdefine bn_mul_comba4 BORINGSSL_PREFIX %+ _bn_mul_comba4 %xdefine bn_mul_comba8 BORINGSSL_PREFIX %+ _bn_mul_comba8 %xdefine bn_mul_consttime BORINGSSL_PREFIX %+ _bn_mul_consttime -%xdefine bn_mul_mont BORINGSSL_PREFIX %+ _bn_mul_mont %xdefine bn_mul_mont_gather5_nohw BORINGSSL_PREFIX %+ _bn_mul_mont_gather5_nohw %xdefine bn_mul_mont_nohw BORINGSSL_PREFIX %+ _bn_mul_mont_nohw +%xdefine bn_mul_mont_words BORINGSSL_PREFIX %+ _bn_mul_mont_words %xdefine bn_mul_small BORINGSSL_PREFIX %+ _bn_mul_small %xdefine BN_mul_word BORINGSSL_PREFIX %+ _BN_mul_word %xdefine bn_mul_words BORINGSSL_PREFIX %+ _bn_mul_words @@ -4324,6 +4450,7 @@ %xdefine CMS_sign BORINGSSL_PREFIX %+ _CMS_sign %xdefine CONF_modules_free BORINGSSL_PREFIX %+ _CONF_modules_free %xdefine CONF_modules_load_file BORINGSSL_PREFIX %+ _CONF_modules_load_file +%xdefine CONF_modules_unload BORINGSSL_PREFIX %+ _CONF_modules_unload %xdefine CONF_parse_list BORINGSSL_PREFIX %+ _CONF_parse_list %xdefine CONF_VALUE_new BORINGSSL_PREFIX %+ _CONF_VALUE_new %xdefine CRL_DIST_POINTS_free BORINGSSL_PREFIX %+ _CRL_DIST_POINTS_free @@ -4458,7 +4585,9 @@ %xdefine CTR_DRBG_generate BORINGSSL_PREFIX %+ _CTR_DRBG_generate %xdefine CTR_DRBG_init BORINGSSL_PREFIX %+ _CTR_DRBG_init %xdefine CTR_DRBG_new BORINGSSL_PREFIX %+ _CTR_DRBG_new +%xdefine CTR_DRBG_new_df BORINGSSL_PREFIX %+ _CTR_DRBG_new_df %xdefine CTR_DRBG_reseed BORINGSSL_PREFIX %+ _CTR_DRBG_reseed +%xdefine CTR_DRBG_reseed_ex BORINGSSL_PREFIX %+ _CTR_DRBG_reseed_ex %xdefine d2i_ASN1_BIT_STRING BORINGSSL_PREFIX %+ _d2i_ASN1_BIT_STRING %xdefine d2i_ASN1_BMPSTRING BORINGSSL_PREFIX %+ _d2i_ASN1_BMPSTRING %xdefine d2i_ASN1_BOOLEAN BORINGSSL_PREFIX %+ _d2i_ASN1_BOOLEAN @@ -4549,7 +4678,6 @@ %xdefine d2i_X509_AUX BORINGSSL_PREFIX %+ _d2i_X509_AUX %xdefine d2i_X509_bio BORINGSSL_PREFIX %+ _d2i_X509_bio %xdefine d2i_X509_CERT_AUX BORINGSSL_PREFIX %+ _d2i_X509_CERT_AUX -%xdefine d2i_X509_CINF BORINGSSL_PREFIX %+ _d2i_X509_CINF %xdefine d2i_X509_CRL BORINGSSL_PREFIX %+ _d2i_X509_CRL %xdefine d2i_X509_CRL_bio BORINGSSL_PREFIX %+ _d2i_X509_CRL_bio %xdefine d2i_X509_CRL_fp BORINGSSL_PREFIX %+ _d2i_X509_CRL_fp @@ -4565,7 +4693,6 @@ %xdefine d2i_X509_REQ_INFO BORINGSSL_PREFIX %+ _d2i_X509_REQ_INFO %xdefine d2i_X509_REVOKED BORINGSSL_PREFIX %+ _d2i_X509_REVOKED %xdefine d2i_X509_SIG BORINGSSL_PREFIX %+ _d2i_X509_SIG -%xdefine d2i_X509_VAL BORINGSSL_PREFIX %+ _d2i_X509_VAL %xdefine DES_decrypt3 BORINGSSL_PREFIX %+ _DES_decrypt3 %xdefine DES_ecb_encrypt BORINGSSL_PREFIX %+ _DES_ecb_encrypt %xdefine DES_ecb_encrypt_ex BORINGSSL_PREFIX %+ _DES_ecb_encrypt_ex @@ -4773,8 +4900,11 @@ %xdefine EC_KEY_new_method BORINGSSL_PREFIX %+ _EC_KEY_new_method %xdefine EC_KEY_oct2key BORINGSSL_PREFIX %+ _EC_KEY_oct2key %xdefine EC_KEY_oct2priv BORINGSSL_PREFIX %+ _EC_KEY_oct2priv +%xdefine ec_key_parse_curve_name BORINGSSL_PREFIX %+ _ec_key_parse_curve_name %xdefine EC_KEY_parse_curve_name BORINGSSL_PREFIX %+ _EC_KEY_parse_curve_name +%xdefine ec_key_parse_parameters BORINGSSL_PREFIX %+ _ec_key_parse_parameters %xdefine EC_KEY_parse_parameters BORINGSSL_PREFIX %+ _EC_KEY_parse_parameters +%xdefine ec_key_parse_private_key BORINGSSL_PREFIX %+ _ec_key_parse_private_key %xdefine EC_KEY_parse_private_key BORINGSSL_PREFIX %+ _EC_KEY_parse_private_key %xdefine EC_KEY_priv2buf BORINGSSL_PREFIX %+ _EC_KEY_priv2buf %xdefine EC_KEY_priv2oct BORINGSSL_PREFIX %+ _EC_KEY_priv2oct @@ -4909,6 +5039,7 @@ %xdefine ED25519_verify BORINGSSL_PREFIX %+ _ED25519_verify %xdefine EDIPARTYNAME_free BORINGSSL_PREFIX %+ _EDIPARTYNAME_free %xdefine EDIPARTYNAME_new BORINGSSL_PREFIX %+ _EDIPARTYNAME_new +%xdefine ENGINE_cleanup BORINGSSL_PREFIX %+ _ENGINE_cleanup %xdefine ENGINE_free BORINGSSL_PREFIX %+ _ENGINE_free %xdefine ENGINE_get_ECDSA_method BORINGSSL_PREFIX %+ _ENGINE_get_ECDSA_method %xdefine ENGINE_get_RSA_method BORINGSSL_PREFIX %+ _ENGINE_get_RSA_method @@ -4921,6 +5052,7 @@ %xdefine ERR_add_error_dataf BORINGSSL_PREFIX %+ _ERR_add_error_dataf %xdefine ERR_clear_error BORINGSSL_PREFIX %+ _ERR_clear_error %xdefine ERR_clear_system_error BORINGSSL_PREFIX %+ _ERR_clear_system_error +%xdefine ERR_equals BORINGSSL_PREFIX %+ _ERR_equals %xdefine ERR_error_string BORINGSSL_PREFIX %+ _ERR_error_string %xdefine ERR_error_string_n BORINGSSL_PREFIX %+ _ERR_error_string_n %xdefine ERR_free_strings BORINGSSL_PREFIX %+ _ERR_free_strings @@ -5147,6 +5279,7 @@ %xdefine EVP_HPKE_KEY_zero BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_zero %xdefine EVP_hpke_p256_hkdf_sha256 BORINGSSL_PREFIX %+ _EVP_hpke_p256_hkdf_sha256 %xdefine EVP_hpke_x25519_hkdf_sha256 BORINGSSL_PREFIX %+ _EVP_hpke_x25519_hkdf_sha256 +%xdefine EVP_hpke_xwing BORINGSSL_PREFIX %+ _EVP_hpke_xwing %xdefine EVP_marshal_digest_algorithm BORINGSSL_PREFIX %+ _EVP_marshal_digest_algorithm %xdefine EVP_marshal_digest_algorithm_no_params BORINGSSL_PREFIX %+ _EVP_marshal_digest_algorithm_no_params %xdefine EVP_marshal_private_key BORINGSSL_PREFIX %+ _EVP_marshal_private_key @@ -5178,6 +5311,7 @@ %xdefine EVP_md5 BORINGSSL_PREFIX %+ _EVP_md5 %xdefine EVP_md5_sha1 BORINGSSL_PREFIX %+ _EVP_md5_sha1 %xdefine EVP_parse_digest_algorithm BORINGSSL_PREFIX %+ _EVP_parse_digest_algorithm +%xdefine EVP_parse_digest_algorithm_nid BORINGSSL_PREFIX %+ _EVP_parse_digest_algorithm_nid %xdefine EVP_parse_private_key BORINGSSL_PREFIX %+ _EVP_parse_private_key %xdefine EVP_parse_public_key BORINGSSL_PREFIX %+ _EVP_parse_public_key %xdefine EVP_PBE_scrypt BORINGSSL_PREFIX %+ _EVP_PBE_scrypt @@ -5230,9 +5364,21 @@ %xdefine EVP_PKEY_derive BORINGSSL_PREFIX %+ _EVP_PKEY_derive %xdefine EVP_PKEY_derive_init BORINGSSL_PREFIX %+ _EVP_PKEY_derive_init %xdefine EVP_PKEY_derive_set_peer BORINGSSL_PREFIX %+ _EVP_PKEY_derive_set_peer +%xdefine EVP_pkey_dsa BORINGSSL_PREFIX %+ _EVP_pkey_dsa +%xdefine EVP_pkey_ec_p224 BORINGSSL_PREFIX %+ _EVP_pkey_ec_p224 +%xdefine EVP_pkey_ec_p256 BORINGSSL_PREFIX %+ _EVP_pkey_ec_p256 +%xdefine EVP_pkey_ec_p384 BORINGSSL_PREFIX %+ _EVP_pkey_ec_p384 +%xdefine EVP_pkey_ec_p521 BORINGSSL_PREFIX %+ _EVP_pkey_ec_p521 +%xdefine EVP_pkey_ed25519 BORINGSSL_PREFIX %+ _EVP_pkey_ed25519 %xdefine EVP_PKEY_encrypt BORINGSSL_PREFIX %+ _EVP_PKEY_encrypt %xdefine EVP_PKEY_encrypt_init BORINGSSL_PREFIX %+ _EVP_PKEY_encrypt_init %xdefine EVP_PKEY_free BORINGSSL_PREFIX %+ _EVP_PKEY_free +%xdefine EVP_PKEY_from_private_key_info BORINGSSL_PREFIX %+ _EVP_PKEY_from_private_key_info +%xdefine EVP_PKEY_from_raw_private_key BORINGSSL_PREFIX %+ _EVP_PKEY_from_raw_private_key +%xdefine EVP_PKEY_from_raw_public_key BORINGSSL_PREFIX %+ _EVP_PKEY_from_raw_public_key +%xdefine EVP_PKEY_from_subject_public_key_info BORINGSSL_PREFIX %+ _EVP_PKEY_from_subject_public_key_info +%xdefine EVP_PKEY_get_ec_curve_nid BORINGSSL_PREFIX %+ _EVP_PKEY_get_ec_curve_nid +%xdefine EVP_PKEY_get_ec_point_conv_form BORINGSSL_PREFIX %+ _EVP_PKEY_get_ec_point_conv_form %xdefine EVP_PKEY_get_raw_private_key BORINGSSL_PREFIX %+ _EVP_PKEY_get_raw_private_key %xdefine EVP_PKEY_get_raw_public_key BORINGSSL_PREFIX %+ _EVP_PKEY_get_raw_public_key %xdefine EVP_PKEY_get0 BORINGSSL_PREFIX %+ _EVP_PKEY_get0 @@ -5258,8 +5404,10 @@ %xdefine EVP_PKEY_print_params BORINGSSL_PREFIX %+ _EVP_PKEY_print_params %xdefine EVP_PKEY_print_private BORINGSSL_PREFIX %+ _EVP_PKEY_print_private %xdefine EVP_PKEY_print_public BORINGSSL_PREFIX %+ _EVP_PKEY_print_public -%xdefine evp_pkey_set_method BORINGSSL_PREFIX %+ _evp_pkey_set_method +%xdefine EVP_pkey_rsa BORINGSSL_PREFIX %+ _EVP_pkey_rsa +%xdefine EVP_pkey_rsa_pss_sha256 BORINGSSL_PREFIX %+ _EVP_pkey_rsa_pss_sha256 %xdefine EVP_PKEY_set_type BORINGSSL_PREFIX %+ _EVP_PKEY_set_type +%xdefine evp_pkey_set0 BORINGSSL_PREFIX %+ _evp_pkey_set0 %xdefine EVP_PKEY_set1_DH BORINGSSL_PREFIX %+ _EVP_PKEY_set1_DH %xdefine EVP_PKEY_set1_DSA BORINGSSL_PREFIX %+ _EVP_PKEY_set1_DSA %xdefine EVP_PKEY_set1_EC_KEY BORINGSSL_PREFIX %+ _EVP_PKEY_set1_EC_KEY @@ -5274,6 +5422,7 @@ %xdefine EVP_PKEY_verify_init BORINGSSL_PREFIX %+ _EVP_PKEY_verify_init %xdefine EVP_PKEY_verify_recover BORINGSSL_PREFIX %+ _EVP_PKEY_verify_recover %xdefine EVP_PKEY_verify_recover_init BORINGSSL_PREFIX %+ _EVP_PKEY_verify_recover_init +%xdefine EVP_pkey_x25519 BORINGSSL_PREFIX %+ _EVP_pkey_x25519 %xdefine EVP_PKEY2PKCS8 BORINGSSL_PREFIX %+ _EVP_PKEY2PKCS8 %xdefine EVP_rc2_40_cbc BORINGSSL_PREFIX %+ _EVP_rc2_40_cbc %xdefine EVP_rc2_cbc BORINGSSL_PREFIX %+ _EVP_rc2_cbc @@ -5310,6 +5459,8 @@ %xdefine FIPS_module_name BORINGSSL_PREFIX %+ _FIPS_module_name %xdefine FIPS_query_algorithm_status BORINGSSL_PREFIX %+ _FIPS_query_algorithm_status %xdefine FIPS_read_counter BORINGSSL_PREFIX %+ _FIPS_read_counter +%xdefine FIPS_service_indicator_after_call BORINGSSL_PREFIX %+ _FIPS_service_indicator_after_call +%xdefine FIPS_service_indicator_before_call BORINGSSL_PREFIX %+ _FIPS_service_indicator_before_call %xdefine FIPS_version BORINGSSL_PREFIX %+ _FIPS_version %xdefine gcm_ghash_avx BORINGSSL_PREFIX %+ _gcm_ghash_avx %xdefine gcm_ghash_clmul BORINGSSL_PREFIX %+ _gcm_ghash_clmul @@ -5485,7 +5636,6 @@ %xdefine i2d_X509_AUX BORINGSSL_PREFIX %+ _i2d_X509_AUX %xdefine i2d_X509_bio BORINGSSL_PREFIX %+ _i2d_X509_bio %xdefine i2d_X509_CERT_AUX BORINGSSL_PREFIX %+ _i2d_X509_CERT_AUX -%xdefine i2d_X509_CINF BORINGSSL_PREFIX %+ _i2d_X509_CINF %xdefine i2d_X509_CRL BORINGSSL_PREFIX %+ _i2d_X509_CRL %xdefine i2d_X509_CRL_bio BORINGSSL_PREFIX %+ _i2d_X509_CRL_bio %xdefine i2d_X509_CRL_fp BORINGSSL_PREFIX %+ _i2d_X509_CRL_fp @@ -5503,7 +5653,6 @@ %xdefine i2d_X509_REVOKED BORINGSSL_PREFIX %+ _i2d_X509_REVOKED %xdefine i2d_X509_SIG BORINGSSL_PREFIX %+ _i2d_X509_SIG %xdefine i2d_X509_tbs BORINGSSL_PREFIX %+ _i2d_X509_tbs -%xdefine i2d_X509_VAL BORINGSSL_PREFIX %+ _i2d_X509_VAL %xdefine i2o_ECPublicKey BORINGSSL_PREFIX %+ _i2o_ECPublicKey %xdefine i2s_ASN1_ENUMERATED BORINGSSL_PREFIX %+ _i2s_ASN1_ENUMERATED %xdefine i2s_ASN1_INTEGER BORINGSSL_PREFIX %+ _i2s_ASN1_INTEGER @@ -5567,6 +5716,17 @@ %xdefine MD5_Update BORINGSSL_PREFIX %+ _MD5_Update %xdefine METHOD_ref BORINGSSL_PREFIX %+ _METHOD_ref %xdefine METHOD_unref BORINGSSL_PREFIX %+ _METHOD_unref +%xdefine MLDSA44_generate_key BORINGSSL_PREFIX %+ _MLDSA44_generate_key +%xdefine MLDSA44_marshal_public_key BORINGSSL_PREFIX %+ _MLDSA44_marshal_public_key +%xdefine MLDSA44_parse_public_key BORINGSSL_PREFIX %+ _MLDSA44_parse_public_key +%xdefine MLDSA44_prehash_finalize BORINGSSL_PREFIX %+ _MLDSA44_prehash_finalize +%xdefine MLDSA44_prehash_init BORINGSSL_PREFIX %+ _MLDSA44_prehash_init +%xdefine MLDSA44_prehash_update BORINGSSL_PREFIX %+ _MLDSA44_prehash_update +%xdefine MLDSA44_private_key_from_seed BORINGSSL_PREFIX %+ _MLDSA44_private_key_from_seed +%xdefine MLDSA44_public_from_private BORINGSSL_PREFIX %+ _MLDSA44_public_from_private +%xdefine MLDSA44_sign BORINGSSL_PREFIX %+ _MLDSA44_sign +%xdefine MLDSA44_sign_message_representative BORINGSSL_PREFIX %+ _MLDSA44_sign_message_representative +%xdefine MLDSA44_verify BORINGSSL_PREFIX %+ _MLDSA44_verify %xdefine MLDSA65_generate_key BORINGSSL_PREFIX %+ _MLDSA65_generate_key %xdefine MLDSA65_marshal_public_key BORINGSSL_PREFIX %+ _MLDSA65_marshal_public_key %xdefine MLDSA65_parse_public_key BORINGSSL_PREFIX %+ _MLDSA65_parse_public_key @@ -5964,6 +6124,7 @@ %xdefine rsa_invalidate_key BORINGSSL_PREFIX %+ _rsa_invalidate_key %xdefine RSA_is_opaque BORINGSSL_PREFIX %+ _RSA_is_opaque %xdefine RSA_marshal_private_key BORINGSSL_PREFIX %+ _RSA_marshal_private_key +%xdefine rsa_marshal_pss_params BORINGSSL_PREFIX %+ _rsa_marshal_pss_params %xdefine RSA_marshal_public_key BORINGSSL_PREFIX %+ _RSA_marshal_public_key %xdefine RSA_new BORINGSSL_PREFIX %+ _RSA_new %xdefine RSA_new_method BORINGSSL_PREFIX %+ _RSA_new_method @@ -5981,6 +6142,7 @@ %xdefine RSA_padding_check_PKCS1_OAEP_mgf1 BORINGSSL_PREFIX %+ _RSA_padding_check_PKCS1_OAEP_mgf1 %xdefine RSA_padding_check_PKCS1_type_1 BORINGSSL_PREFIX %+ _RSA_padding_check_PKCS1_type_1 %xdefine RSA_parse_private_key BORINGSSL_PREFIX %+ _RSA_parse_private_key +%xdefine rsa_parse_pss_params BORINGSSL_PREFIX %+ _rsa_parse_pss_params %xdefine RSA_parse_public_key BORINGSSL_PREFIX %+ _RSA_parse_public_key %xdefine rsa_pkey_meth BORINGSSL_PREFIX %+ _rsa_pkey_meth %xdefine RSA_print BORINGSSL_PREFIX %+ _RSA_print @@ -5991,8 +6153,11 @@ %xdefine rsa_private_transform BORINGSSL_PREFIX %+ _rsa_private_transform %xdefine rsa_private_transform_no_self_test BORINGSSL_PREFIX %+ _rsa_private_transform_no_self_test %xdefine RSA_PSS_PARAMS_free BORINGSSL_PREFIX %+ _RSA_PSS_PARAMS_free +%xdefine rsa_pss_params_get_md BORINGSSL_PREFIX %+ _rsa_pss_params_get_md %xdefine RSA_PSS_PARAMS_it BORINGSSL_PREFIX %+ _RSA_PSS_PARAMS_it %xdefine RSA_PSS_PARAMS_new BORINGSSL_PREFIX %+ _RSA_PSS_PARAMS_new +%xdefine rsa_pss_sha256_asn1_meth BORINGSSL_PREFIX %+ _rsa_pss_sha256_asn1_meth +%xdefine rsa_pss_sha256_pkey_meth BORINGSSL_PREFIX %+ _rsa_pss_sha256_pkey_meth %xdefine RSA_public_decrypt BORINGSSL_PREFIX %+ _RSA_public_decrypt %xdefine RSA_public_encrypt BORINGSSL_PREFIX %+ _RSA_public_encrypt %xdefine RSA_public_key_from_bytes BORINGSSL_PREFIX %+ _RSA_public_key_from_bytes @@ -6442,10 +6607,13 @@ %xdefine X509_add1_ext_i2d BORINGSSL_PREFIX %+ _X509_add1_ext_i2d %xdefine X509_add1_reject_object BORINGSSL_PREFIX %+ _X509_add1_reject_object %xdefine X509_add1_trust_object BORINGSSL_PREFIX %+ _X509_add1_trust_object +%xdefine x509_algor_cleanup BORINGSSL_PREFIX %+ _x509_algor_cleanup %xdefine X509_ALGOR_cmp BORINGSSL_PREFIX %+ _X509_ALGOR_cmp +%xdefine X509_ALGOR_copy BORINGSSL_PREFIX %+ _X509_ALGOR_copy %xdefine X509_ALGOR_dup BORINGSSL_PREFIX %+ _X509_ALGOR_dup %xdefine X509_ALGOR_free BORINGSSL_PREFIX %+ _X509_ALGOR_free %xdefine X509_ALGOR_get0 BORINGSSL_PREFIX %+ _X509_ALGOR_get0 +%xdefine x509_algor_init BORINGSSL_PREFIX %+ _x509_algor_init %xdefine X509_ALGOR_it BORINGSSL_PREFIX %+ _X509_ALGOR_it %xdefine X509_ALGOR_new BORINGSSL_PREFIX %+ _X509_ALGOR_new %xdefine X509_ALGOR_set_md BORINGSSL_PREFIX %+ _X509_ALGOR_set_md @@ -6482,9 +6650,6 @@ %xdefine X509_check_private_key BORINGSSL_PREFIX %+ _X509_check_private_key %xdefine X509_check_purpose BORINGSSL_PREFIX %+ _X509_check_purpose %xdefine X509_check_trust BORINGSSL_PREFIX %+ _X509_check_trust -%xdefine X509_CINF_free BORINGSSL_PREFIX %+ _X509_CINF_free -%xdefine X509_CINF_it BORINGSSL_PREFIX %+ _X509_CINF_it -%xdefine X509_CINF_new BORINGSSL_PREFIX %+ _X509_CINF_new %xdefine X509_cmp BORINGSSL_PREFIX %+ _X509_cmp %xdefine X509_cmp_current_time BORINGSSL_PREFIX %+ _X509_cmp_current_time %xdefine X509_cmp_time BORINGSSL_PREFIX %+ _X509_cmp_time @@ -6620,6 +6785,8 @@ %xdefine X509_LOOKUP_load_file BORINGSSL_PREFIX %+ _X509_LOOKUP_load_file %xdefine x509_marshal_algorithm BORINGSSL_PREFIX %+ _x509_marshal_algorithm %xdefine x509_marshal_name BORINGSSL_PREFIX %+ _x509_marshal_name +%xdefine x509_marshal_public_key BORINGSSL_PREFIX %+ _x509_marshal_public_key +%xdefine x509_marshal_tbs_cert BORINGSSL_PREFIX %+ _x509_marshal_tbs_cert %xdefine X509_NAME_add_entry BORINGSSL_PREFIX %+ _X509_NAME_add_entry %xdefine X509_NAME_add_entry_by_NID BORINGSSL_PREFIX %+ _X509_NAME_add_entry_by_NID %xdefine X509_NAME_add_entry_by_OBJ BORINGSSL_PREFIX %+ _X509_NAME_add_entry_by_OBJ @@ -6663,23 +6830,29 @@ %xdefine X509_OBJECT_get_type BORINGSSL_PREFIX %+ _X509_OBJECT_get_type %xdefine X509_OBJECT_get0_X509 BORINGSSL_PREFIX %+ _X509_OBJECT_get0_X509 %xdefine X509_OBJECT_new BORINGSSL_PREFIX %+ _X509_OBJECT_new +%xdefine x509_parse_algorithm BORINGSSL_PREFIX %+ _x509_parse_algorithm %xdefine X509_parse_from_buffer BORINGSSL_PREFIX %+ _X509_parse_from_buffer +%xdefine x509_parse_public_key BORINGSSL_PREFIX %+ _x509_parse_public_key +%xdefine X509_parse_with_algorithms BORINGSSL_PREFIX %+ _X509_parse_with_algorithms %xdefine X509_policy_check BORINGSSL_PREFIX %+ _X509_policy_check %xdefine X509_print BORINGSSL_PREFIX %+ _X509_print %xdefine X509_print_ex BORINGSSL_PREFIX %+ _X509_print_ex %xdefine X509_print_ex_fp BORINGSSL_PREFIX %+ _X509_print_ex_fp %xdefine X509_print_fp BORINGSSL_PREFIX %+ _X509_print_fp %xdefine x509_print_rsa_pss_params BORINGSSL_PREFIX %+ _x509_print_rsa_pss_params +%xdefine x509_pubkey_cleanup BORINGSSL_PREFIX %+ _x509_pubkey_cleanup %xdefine X509_pubkey_digest BORINGSSL_PREFIX %+ _X509_pubkey_digest %xdefine X509_PUBKEY_free BORINGSSL_PREFIX %+ _X509_PUBKEY_free %xdefine X509_PUBKEY_get BORINGSSL_PREFIX %+ _X509_PUBKEY_get %xdefine X509_PUBKEY_get0 BORINGSSL_PREFIX %+ _X509_PUBKEY_get0 %xdefine X509_PUBKEY_get0_param BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_param %xdefine X509_PUBKEY_get0_public_key BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_public_key +%xdefine x509_pubkey_init BORINGSSL_PREFIX %+ _x509_pubkey_init %xdefine X509_PUBKEY_it BORINGSSL_PREFIX %+ _X509_PUBKEY_it %xdefine X509_PUBKEY_new BORINGSSL_PREFIX %+ _X509_PUBKEY_new %xdefine X509_PUBKEY_set BORINGSSL_PREFIX %+ _X509_PUBKEY_set %xdefine X509_PUBKEY_set0_param BORINGSSL_PREFIX %+ _X509_PUBKEY_set0_param +%xdefine x509_pubkey_set1 BORINGSSL_PREFIX %+ _x509_pubkey_set1 %xdefine X509_PURPOSE_get_by_sname BORINGSSL_PREFIX %+ _X509_PURPOSE_get_by_sname %xdefine X509_PURPOSE_get_id BORINGSSL_PREFIX %+ _X509_PURPOSE_get_id %xdefine X509_PURPOSE_get_trust BORINGSSL_PREFIX %+ _X509_PURPOSE_get_trust @@ -6763,6 +6936,7 @@ %xdefine X509_SIG_new BORINGSSL_PREFIX %+ _X509_SIG_new %xdefine X509_sign BORINGSSL_PREFIX %+ _X509_sign %xdefine X509_sign_ctx BORINGSSL_PREFIX %+ _X509_sign_ctx +%xdefine x509_sign_to_bit_string BORINGSSL_PREFIX %+ _x509_sign_to_bit_string %xdefine X509_signature_dump BORINGSSL_PREFIX %+ _X509_signature_dump %xdefine X509_signature_print BORINGSSL_PREFIX %+ _X509_signature_print %xdefine X509_STORE_add_cert BORINGSSL_PREFIX %+ _X509_STORE_add_cert @@ -6827,9 +7001,6 @@ %xdefine X509_time_adj_ex BORINGSSL_PREFIX %+ _X509_time_adj_ex %xdefine X509_trust_clear BORINGSSL_PREFIX %+ _X509_trust_clear %xdefine X509_up_ref BORINGSSL_PREFIX %+ _X509_up_ref -%xdefine X509_VAL_free BORINGSSL_PREFIX %+ _X509_VAL_free -%xdefine X509_VAL_it BORINGSSL_PREFIX %+ _X509_VAL_it -%xdefine X509_VAL_new BORINGSSL_PREFIX %+ _X509_VAL_new %xdefine X509_verify BORINGSSL_PREFIX %+ _X509_verify %xdefine X509_verify_cert BORINGSSL_PREFIX %+ _X509_verify_cert %xdefine X509_verify_cert_error_string BORINGSSL_PREFIX %+ _X509_verify_cert_error_string @@ -6855,6 +7026,7 @@ %xdefine X509_VERIFY_PARAM_set1_ip BORINGSSL_PREFIX %+ _X509_VERIFY_PARAM_set1_ip %xdefine X509_VERIFY_PARAM_set1_ip_asc BORINGSSL_PREFIX %+ _X509_VERIFY_PARAM_set1_ip_asc %xdefine X509_VERIFY_PARAM_set1_policies BORINGSSL_PREFIX %+ _X509_VERIFY_PARAM_set1_policies +%xdefine x509_verify_signature BORINGSSL_PREFIX %+ _x509_verify_signature %xdefine x509v3_a2i_ipadd BORINGSSL_PREFIX %+ _x509v3_a2i_ipadd %xdefine X509v3_add_ext BORINGSSL_PREFIX %+ _X509v3_add_ext %xdefine X509V3_add_standard_extensions BORINGSSL_PREFIX %+ _X509V3_add_standard_extensions diff --git a/Sources/CCryptoBoringSSL/include/experimental/CCryptoBoringSSL_kyber.h b/Sources/CCryptoBoringSSL/include/experimental/CCryptoBoringSSL_kyber.h deleted file mode 100644 index 43aaaa4de..000000000 --- a/Sources/CCryptoBoringSSL/include/experimental/CCryptoBoringSSL_kyber.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2023 The BoringSSL Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef OPENSSL_HEADER_KYBER_H -#define OPENSSL_HEADER_KYBER_H - -#include "CCryptoBoringSSL_base.h" // IWYU pragma: export - -#if defined(__cplusplus) -extern "C" { -#endif - - -#if defined(OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER) -// This header implements experimental, draft versions of not-yet-standardized -// primitives. When the standard is complete, these functions will be removed -// and replaced with the final, incompatible standard version. They are -// available now for short-lived experiments, but must not be deployed anywhere -// durable, such as a long-lived key store. To use these functions define -// OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER - -// Kyber768. -// -// This implements the round-3 specification of Kyber, defined at -// https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf - - -// KYBER_public_key contains a Kyber768 public key. The contents of this -// object should never leave the address space since the format is unstable. -struct KYBER_public_key { - union { - uint8_t bytes[512 * (3 + 9) + 32 + 32]; - uint16_t alignment; - } opaque; -}; - -// KYBER_private_key contains a Kyber768 private key. The contents of this -// object should never leave the address space since the format is unstable. -struct KYBER_private_key { - union { - uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32]; - uint16_t alignment; - } opaque; -}; - -// KYBER_PUBLIC_KEY_BYTES is the number of bytes in an encoded Kyber768 public -// key. -#define KYBER_PUBLIC_KEY_BYTES 1184 - -// KYBER_SHARED_SECRET_BYTES is the number of bytes in the Kyber768 shared -// secret. Although the round-3 specification has a variable-length output, the -// final ML-KEM construction is expected to use a fixed 32-byte output. To -// simplify the future transition, we apply the same restriction. -#define KYBER_SHARED_SECRET_BYTES 32 - -// KYBER_generate_key generates a random public/private key pair, writes the -// encoded public key to |out_encoded_public_key| and sets |out_private_key| to -// the private key. -OPENSSL_EXPORT void KYBER_generate_key( - uint8_t out_encoded_public_key[KYBER_PUBLIC_KEY_BYTES], - struct KYBER_private_key *out_private_key); - -// KYBER_public_from_private sets |*out_public_key| to the public key that -// corresponds to |private_key|. (This is faster than parsing the output of -// |KYBER_generate_key| if, for some reason, you need to encapsulate to a key -// that was just generated.) -OPENSSL_EXPORT void KYBER_public_from_private( - struct KYBER_public_key *out_public_key, - const struct KYBER_private_key *private_key); - -// KYBER_CIPHERTEXT_BYTES is number of bytes in the Kyber768 ciphertext. -#define KYBER_CIPHERTEXT_BYTES 1088 - -// KYBER_encap encrypts a random shared secret for |public_key|, writes the -// ciphertext to |out_ciphertext|, and writes the random shared secret to -// |out_shared_secret|. -OPENSSL_EXPORT void KYBER_encap( - uint8_t out_ciphertext[KYBER_CIPHERTEXT_BYTES], - uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES], - const struct KYBER_public_key *public_key); - -// KYBER_decap decrypts a shared secret from |ciphertext| using |private_key| -// and writes it to |out_shared_secret|. If |ciphertext| is invalid, -// |out_shared_secret| is filled with a key that will always be the same for the -// same |ciphertext| and |private_key|, but which appears to be random unless -// one has access to |private_key|. These alternatives occur in constant time. -// Any subsequent symmetric encryption using |out_shared_secret| must use an -// authenticated encryption scheme in order to discover the decapsulation -// failure. -OPENSSL_EXPORT void KYBER_decap( - uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES], - const uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES], - const struct KYBER_private_key *private_key); - - -// Serialisation of keys. - -// KYBER_marshal_public_key serializes |public_key| to |out| in the standard -// format for Kyber public keys. It returns one on success or zero on allocation -// error. -OPENSSL_EXPORT int KYBER_marshal_public_key( - CBB *out, const struct KYBER_public_key *public_key); - -// KYBER_parse_public_key parses a public key, in the format generated by -// |KYBER_marshal_public_key|, from |in| and writes the result to -// |out_public_key|. It returns one on success or zero on parse error or if -// there are trailing bytes in |in|. -OPENSSL_EXPORT int KYBER_parse_public_key( - struct KYBER_public_key *out_public_key, CBS *in); - -// KYBER_marshal_private_key serializes |private_key| to |out| in the standard -// format for Kyber private keys. It returns one on success or zero on -// allocation error. -OPENSSL_EXPORT int KYBER_marshal_private_key( - CBB *out, const struct KYBER_private_key *private_key); - -// KYBER_PRIVATE_KEY_BYTES is the length of the data produced by -// |KYBER_marshal_private_key|. -#define KYBER_PRIVATE_KEY_BYTES 2400 - -// KYBER_parse_private_key parses a private key, in the format generated by -// |KYBER_marshal_private_key|, from |in| and writes the result to -// |out_private_key|. It returns one on success or zero on parse error or if -// there are trailing bytes in |in|. -OPENSSL_EXPORT int KYBER_parse_private_key( - struct KYBER_private_key *out_private_key, CBS *in); - -#endif // OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_KYBER_H diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_polyfill_platform.c.inc b/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_polyfill_platform.c.inc new file mode 100644 index 000000000..ec6c3a55d --- /dev/null +++ b/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_polyfill_platform.c.inc @@ -0,0 +1,66 @@ +// Generated from Bedrock code in Fiat Cryptogrpahy. Avoid editing directly. + +static inline br_word_t br_full_add(br_word_t x, br_word_t y, br_word_t carry, br_word_t* _sum) { + br_word_t carry_out, sum; + x = x+carry; + carry_out = (br_word_t)(x>27)&63)+1)>>1; + M = ((br_word_t)1<<(n&(sizeof(br_word_t)*8-1)))-1; + ll = (a&M)*(b&M); + lh = (a&M)*(b>>(n&(sizeof(br_word_t)*8-1))); + hl = (a>>(n&(sizeof(br_word_t)*8-1)))*(b&M); + hh = (a>>(n&(sizeof(br_word_t)*8-1)))*(b>>(n&(sizeof(br_word_t)*8-1))); + second_halfword_w_oflow = ((ll>>(n&(sizeof(br_word_t)*8-1)))+(lh&M))+(hl&M); + high = ((hh+(lh>>(n&(sizeof(br_word_t)*8-1))))+(hl>>(n&(sizeof(br_word_t)*8-1))))+(second_halfword_w_oflow>>(n&(sizeof(br_word_t)*8-1))); + low = (second_halfword_w_oflow<<(n&(sizeof(br_word_t)*8-1)))+(ll&M); + *_low = low; + return high; +} + +static inline br_word_t br_value_barrier(br_word_t a) { + /*skip*/ + return a; +} + +static inline br_word_t br_declassify(br_word_t a) { + /*skip*/ + return a; +} + +static inline br_word_t br_broadcast_negative(br_word_t x) { + br_word_t y; + y = (br_word_t)((br_signed_t)x>>((((0u-(br_word_t)1)>>27)&63)&(sizeof(br_word_t)*8-1))); + y = br_value_barrier(y); + return y; +} + +static inline br_word_t br_broadcast_nonzero(br_word_t x) { + br_word_t y; + y = br_broadcast_negative(x|(0u-x)); + return y; +} + +static inline br_word_t br_cmov(br_word_t c, br_word_t vnz, br_word_t vz) { + br_word_t r, m; + m = br_broadcast_nonzero(c); + r = (m&vnz)|((~m)&vz); + return r; +} diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_bareminimum.c.inc b/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_bareminimum.c.inc new file mode 100644 index 000000000..a03388bd0 --- /dev/null +++ b/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_bareminimum.c.inc @@ -0,0 +1,47 @@ +#ifndef BEDROCK_UNVERIFIED_BAREMINIMUM_INC_H_ +#define BEDROCK_UNVERIFIED_BAREMINIMUM_INC_H_ + +static_assert(sizeof(br_word_t) == sizeof(br_signed_t), ""); +static_assert(UINTPTR_MAX <= BR_WORD_MAX, ""); + +// "An object shall have its stored value accessed only ... a character type." + +static inline br_word_t _br_load1(br_word_t a) { + return *((uint8_t *)a); +} + +static inline br_word_t _br_load2(br_word_t a) { + uint16_t r = 0; + memcpy(&r, (void *)a, sizeof(r)); + return r; +} + +static inline br_word_t _br_load4(br_word_t a) { + uint32_t r = 0; + memcpy(&r, (void *)a, sizeof(r)); + return r; +} + +static inline br_word_t _br_load(br_word_t a) { + br_word_t r = 0; + memcpy(&r, (void *)a, sizeof(r)); + return r; +} + +static inline void _br_store1(br_word_t a, uint8_t v) { + *((uint8_t *)a) = v; +} + +static inline void _br_store2(br_word_t a, uint16_t v) { + memcpy((void *)a, &v, sizeof(v)); +} + +static inline void _br_store4(br_word_t a, uint32_t v) { + memcpy((void *)a, &v, sizeof(v)); +} + +static inline void _br_store(br_word_t a, br_word_t v) { + memcpy((void *)a, &v, sizeof(v)); +} + +#endif // BEDROCK_UNVERIFIED_BAREMINIMUM_INC_H_ diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_platform.c.inc b/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_platform.c.inc new file mode 100644 index 000000000..89fe7d05d --- /dev/null +++ b/Sources/CCryptoBoringSSL/third_party/fiat/bedrock_unverified_platform.c.inc @@ -0,0 +1,125 @@ +#ifndef BEDROCK_UNVERIFIED_PLATFORM_INC_H_ +#define BEDROCK_UNVERIFIED_PLATFORM_INC_H_ + +// This file is a manually maintained and audited replacement for +// bedrock_polyfill_platform.c.inc with tests in bedrock_platform_test.cc + +#include "../../crypto/internal.h" + +#if defined(OPENSSL_64_BIT) +#define BR_WORD_MAX UINT64_MAX +typedef uint64_t br_word_t; +typedef int64_t br_signed_t; +#elif defined(OPENSSL_32_BIT) +#define BR_WORD_MAX UINT32_MAX +typedef uint32_t br_word_t; +typedef int32_t br_signed_t; +#else +#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +#endif + +static_assert(sizeof(br_word_t) == sizeof(crypto_word_t)); + +// Scalar memory operations + +#include "../../third_party/fiat/bedrock_unverified_bareminimum.c.inc" + +// Bulk memory operations + +static inline void br_memcpy(br_word_t d, br_word_t s, br_word_t n) { + OPENSSL_memcpy((void *)d, (const void *)s, n); +} + +static inline void br_memset(br_word_t d, br_word_t v, br_word_t n) { + OPENSSL_memset((void *)d, v, n); +} + +static inline void br_memcxor(uintptr_t d, uintptr_t s, uintptr_t n, uintptr_t mask) { + constant_time_conditional_memxor((void*)d, (void*)s, n, mask); +} + +// CPU Arithmetic + +static inline br_word_t br_full_add(br_word_t x, br_word_t y, br_word_t carry, + br_word_t *_sum) { + br_word_t carry_out = 0; + static_assert(sizeof(br_word_t) == sizeof(crypto_word_t)); + *_sum = CRYPTO_addc_w(x, y, carry, &carry_out); + return carry_out; +} + +static inline br_word_t br_full_sub(br_word_t x, br_word_t y, br_word_t borrow, + br_word_t *_diff) { + br_word_t borrow_out = 0; + static_assert(sizeof(br_word_t) == sizeof(crypto_word_t)); + *_diff = CRYPTO_subc_w(x, y, borrow, &borrow_out); + return borrow_out; +} + +static inline br_word_t br_full_mul(br_word_t a, br_word_t b, br_word_t *_low) { +#if BR_WORD_MAX == UINT32_MAX + uint64_t r = (uint64_t)a * b; + *_low = r; + return r >> 32; +#elif defined(BORINGSSL_HAS_UINT128) + uint128_t r = (uint128_t)a * b; + *_low = r; + return r >> 64; +#elif defined(_M_X64) + uint64_t hi; + *_low = _umul128(a, b, &hi); + return hi; +#elif defined(_M_ARM64) + *_low = a * b; + return __umulh(a, b); +#else +#error "need 64 x 64 -> 128 multiplication" +#endif +} + +// Constant-time computations + +static inline br_word_t br_value_barrier(br_word_t a) { + static_assert(sizeof(br_word_t) == sizeof(crypto_word_t)); + return value_barrier_w(a); +} + +static inline br_word_t br_declassify(br_word_t a) { + static_assert(sizeof(br_word_t) == sizeof(crypto_word_t)); + return constant_time_declassify_w(a); +} + +static inline br_word_t br_broadcast_negative(br_word_t x) { + return br_value_barrier((br_signed_t)x >> (sizeof(br_word_t) * 8 - 1)); +} + +static inline br_word_t br_broadcast_nonzero(br_word_t x) { + return br_broadcast_negative(x | (0u - x)); +} + +static inline br_word_t br_cmov(br_word_t c, br_word_t vnz, br_word_t vz) { +#if !defined(OPENSSL_NO_ASM) && (defined(__GNUC__) || defined(__clang__)) && \ + defined(__x86_64__) + __asm__( + "testq %[c], %[c]\n" + "cmovzq %[vz], %[vnz]" + : [vnz] "+r"(vnz) + : [vz] "r"(vz), [c] "r"(c) + : "cc"); + return vnz; +#elif !defined(OPENSSL_NO_ASM) && (defined(__GNUC__) || defined(__clang__)) && \ + defined(__i386__) + __asm__( + "testl %[c], %[c]\n" // test%z[c] gives "invalid operand" on clang 16.0.6 + "cmovzl %[vz], %[vnz]" + : [vnz] "+r"(vnz) + : [vz] "r"(vz), [c] "r"(c) + : "cc"); + return vnz; +#else + br_word_t m = br_broadcast_nonzero(c); + return (m & vnz) | (~m & vz); +#endif +} + +#endif // BEDROCK_UNVERIFIED_PLATFORM_INC_H_ diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/p256_64.h b/Sources/CCryptoBoringSSL/third_party/fiat/p256_64.h index 0aaac28c5..ddb73ae70 100644 --- a/Sources/CCryptoBoringSSL/third_party/fiat/p256_64.h +++ b/Sources/CCryptoBoringSSL/third_party/fiat/p256_64.h @@ -1,4 +1,6 @@ #include +#include "bedrock_unverified_platform.c.inc" +#include "p256_field_64.br.c.inc" #include "../../crypto/internal.h" #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) && defined(__x86_64__) @@ -175,6 +177,7 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_cmovznz_u64(uint64_t* out1, fiat_p25 * */ static FIAT_P256_FIAT_INLINE void fiat_p256_mul(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { + // NOTE: edited by hand, see third_party/fiat/README.md #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) && defined(__x86_64__) if (CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable() && CRYPTO_is_ADX_capable()) { @@ -489,6 +492,7 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_mul(fiat_p256_montgomery_domain_fiel * */ static FIAT_P256_FIAT_INLINE void fiat_p256_square(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1) { + // NOTE: edited by hand, see third_party/fiat/README.md #if !defined(OPENSSL_NO_ASM) && defined(__GNUC__) && defined(__x86_64__) if (CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable() && CRYPTO_is_ADX_capable()) { @@ -804,45 +808,8 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_square(fiat_p256_montgomery_domain_f * */ static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { - uint64_t x1; - fiat_p256_uint1 x2; - uint64_t x3; - fiat_p256_uint1 x4; - uint64_t x5; - fiat_p256_uint1 x6; - uint64_t x7; - fiat_p256_uint1 x8; - uint64_t x9; - fiat_p256_uint1 x10; - uint64_t x11; - fiat_p256_uint1 x12; - uint64_t x13; - fiat_p256_uint1 x14; - uint64_t x15; - fiat_p256_uint1 x16; - uint64_t x17; - fiat_p256_uint1 x18; - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - fiat_p256_addcarryx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); - fiat_p256_addcarryx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1])); - fiat_p256_addcarryx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2])); - fiat_p256_addcarryx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3])); - fiat_p256_subborrowx_u64(&x9, &x10, 0x0, x1, UINT64_C(0xffffffffffffffff)); - fiat_p256_subborrowx_u64(&x11, &x12, x10, x3, UINT32_C(0xffffffff)); - fiat_p256_subborrowx_u64(&x13, &x14, x12, x5, 0x0); - fiat_p256_subborrowx_u64(&x15, &x16, x14, x7, UINT64_C(0xffffffff00000001)); - fiat_p256_subborrowx_u64(&x17, &x18, x16, x8, 0x0); - fiat_p256_cmovznz_u64(&x19, x18, x9, x1); - fiat_p256_cmovznz_u64(&x20, x18, x11, x3); - fiat_p256_cmovznz_u64(&x21, x18, x13, x5); - fiat_p256_cmovznz_u64(&x22, x18, x15, x7); - out1[0] = x19; - out1[1] = x20; - out1[2] = x21; - out1[3] = x22; + // NOTE: edited by hand, see third_party/fiat/README.md + p256_coord_add((br_word_t)out1, (br_word_t)arg1, (br_word_t)arg2); } /* @@ -857,36 +824,8 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_fiel * */ static FIAT_P256_FIAT_INLINE void fiat_p256_sub(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { - uint64_t x1; - fiat_p256_uint1 x2; - uint64_t x3; - fiat_p256_uint1 x4; - uint64_t x5; - fiat_p256_uint1 x6; - uint64_t x7; - fiat_p256_uint1 x8; - uint64_t x9; - uint64_t x10; - fiat_p256_uint1 x11; - uint64_t x12; - fiat_p256_uint1 x13; - uint64_t x14; - fiat_p256_uint1 x15; - uint64_t x16; - fiat_p256_uint1 x17; - fiat_p256_subborrowx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); - fiat_p256_subborrowx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1])); - fiat_p256_subborrowx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2])); - fiat_p256_subborrowx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3])); - fiat_p256_cmovznz_u64(&x9, x8, 0x0, UINT64_C(0xffffffffffffffff)); - fiat_p256_addcarryx_u64(&x10, &x11, 0x0, x1, x9); - fiat_p256_addcarryx_u64(&x12, &x13, x11, x3, (x9 & UINT32_C(0xffffffff))); - fiat_p256_addcarryx_u64(&x14, &x15, x13, x5, 0x0); - fiat_p256_addcarryx_u64(&x16, &x17, x15, x7, (x9 & UINT64_C(0xffffffff00000001))); - out1[0] = x10; - out1[1] = x12; - out1[2] = x14; - out1[3] = x16; + // NOTE: edited by hand, see third_party/fiat/README.md + p256_coord_sub((br_word_t)out1, (br_word_t)arg1, (br_word_t)arg2); } /* diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/p256_64_msvc.h b/Sources/CCryptoBoringSSL/third_party/fiat/p256_64_msvc.h index 8b65a3734..aff43d359 100644 --- a/Sources/CCryptoBoringSSL/third_party/fiat/p256_64_msvc.h +++ b/Sources/CCryptoBoringSSL/third_party/fiat/p256_64_msvc.h @@ -17,6 +17,8 @@ /* twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in */ /* if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 */ +#include "bedrock_unverified_platform.c.inc" +#include "p256_field_64.br.c.inc" #include #include #if defined(_M_X64) @@ -771,45 +773,8 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_square(fiat_p256_montgomery_domain_f * */ static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { - uint64_t x1; - fiat_p256_uint1 x2; - uint64_t x3; - fiat_p256_uint1 x4; - uint64_t x5; - fiat_p256_uint1 x6; - uint64_t x7; - fiat_p256_uint1 x8; - uint64_t x9; - fiat_p256_uint1 x10; - uint64_t x11; - fiat_p256_uint1 x12; - uint64_t x13; - fiat_p256_uint1 x14; - uint64_t x15; - fiat_p256_uint1 x16; - uint64_t x17; - fiat_p256_uint1 x18; - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - fiat_p256_addcarryx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); - fiat_p256_addcarryx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1])); - fiat_p256_addcarryx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2])); - fiat_p256_addcarryx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3])); - fiat_p256_subborrowx_u64(&x9, &x10, 0x0, x1, UINT64_C(0xffffffffffffffff)); - fiat_p256_subborrowx_u64(&x11, &x12, x10, x3, UINT32_C(0xffffffff)); - fiat_p256_subborrowx_u64(&x13, &x14, x12, x5, 0x0); - fiat_p256_subborrowx_u64(&x15, &x16, x14, x7, UINT64_C(0xffffffff00000001)); - fiat_p256_subborrowx_u64(&x17, &x18, x16, x8, 0x0); - fiat_p256_cmovznz_u64(&x19, x18, x9, x1); - fiat_p256_cmovznz_u64(&x20, x18, x11, x3); - fiat_p256_cmovznz_u64(&x21, x18, x13, x5); - fiat_p256_cmovznz_u64(&x22, x18, x15, x7); - out1[0] = x19; - out1[1] = x20; - out1[2] = x21; - out1[3] = x22; + // NOTE: edited by hand, see third_party/fiat/README.md + p256_coord_add((br_word_t)out1, (br_word_t)arg1, (br_word_t)arg2); } /* @@ -824,36 +789,8 @@ static FIAT_P256_FIAT_INLINE void fiat_p256_add(fiat_p256_montgomery_domain_fiel * */ static FIAT_P256_FIAT_INLINE void fiat_p256_sub(fiat_p256_montgomery_domain_field_element out1, const fiat_p256_montgomery_domain_field_element arg1, const fiat_p256_montgomery_domain_field_element arg2) { - uint64_t x1; - fiat_p256_uint1 x2; - uint64_t x3; - fiat_p256_uint1 x4; - uint64_t x5; - fiat_p256_uint1 x6; - uint64_t x7; - fiat_p256_uint1 x8; - uint64_t x9; - uint64_t x10; - fiat_p256_uint1 x11; - uint64_t x12; - fiat_p256_uint1 x13; - uint64_t x14; - fiat_p256_uint1 x15; - uint64_t x16; - fiat_p256_uint1 x17; - fiat_p256_subborrowx_u64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); - fiat_p256_subborrowx_u64(&x3, &x4, x2, (arg1[1]), (arg2[1])); - fiat_p256_subborrowx_u64(&x5, &x6, x4, (arg1[2]), (arg2[2])); - fiat_p256_subborrowx_u64(&x7, &x8, x6, (arg1[3]), (arg2[3])); - fiat_p256_cmovznz_u64(&x9, x8, 0x0, UINT64_C(0xffffffffffffffff)); - fiat_p256_addcarryx_u64(&x10, &x11, 0x0, x1, x9); - fiat_p256_addcarryx_u64(&x12, &x13, x11, x3, (x9 & UINT32_C(0xffffffff))); - fiat_p256_addcarryx_u64(&x14, &x15, x13, x5, 0x0); - fiat_p256_addcarryx_u64(&x16, &x17, x15, x7, (x9 & UINT64_C(0xffffffff00000001))); - out1[0] = x10; - out1[1] = x12; - out1[2] = x14; - out1[3] = x16; + // NOTE: edited by hand, see third_party/fiat/README.md + p256_coord_sub((br_word_t)out1, (br_word_t)arg1, (br_word_t)arg2); } /* diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/p256_field.c.inc b/Sources/CCryptoBoringSSL/third_party/fiat/p256_field.c.inc new file mode 100644 index 000000000..047d61bf7 --- /dev/null +++ b/Sources/CCryptoBoringSSL/third_party/fiat/p256_field.c.inc @@ -0,0 +1,26 @@ +#include +#include "bedrock_unverified_platform.c.inc" + +#if defined(BORINGSSL_HAS_UINT128) +#include "p256_64.h" +#elif defined(OPENSSL_64_BIT) +#include "p256_64_msvc.h" +#else +#include "p256_field_32.br.c.inc" +#include "p256_32.h" +// the 32-bit Bedrock-generated field halving calls Fiat-C code for add, sub +static inline void p256_coord_add(br_word_t out, br_word_t x, br_word_t y) { + fiat_p256_add((uint32_t*)out, (const uint32_t*)x, (const uint32_t*)y); +} +static inline void p256_coord_sub(br_word_t out, br_word_t x, br_word_t y) { + fiat_p256_sub((uint32_t*)out, (const uint32_t*)x, (const uint32_t*)y); +} +#endif + +// the Bedrock-generated point operations call Fiat-C or Fiat-x86 mul, sqr +static inline void p256_coord_mul(br_word_t out, br_word_t x, br_word_t y) { + fiat_p256_mul((br_word_t*)out, (const br_word_t*)x, (const br_word_t*)y); +} +static inline void p256_coord_sqr(br_word_t out, br_word_t x) { + fiat_p256_square((br_word_t*)out, (const br_word_t*)x); +} diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/p256_field_32.br.c.inc b/Sources/CCryptoBoringSSL/third_party/fiat/p256_field_32.br.c.inc new file mode 100644 index 000000000..e681dcb55 --- /dev/null +++ b/Sources/CCryptoBoringSSL/third_party/fiat/p256_field_32.br.c.inc @@ -0,0 +1,71 @@ +// Generated from Bedrock code in Fiat Cryptography. Avoid editing directly. + +static inline br_word_t shrd(br_word_t lo, br_word_t hi, br_word_t n) { + br_word_t res; + res = lo>>(n&(sizeof(br_word_t)*8-1)); + if (n) { + res = (hi<<((((((0u-(br_word_t)1)>>27)&63)+1)-n)&(sizeof(br_word_t)*8-1)))|res; + } else { + /*skip*/ + } + return res; +} + +static inline br_word_t p256_coord_nonzero(br_word_t p_x) { + br_word_t nz; + nz = (((_br_load(p_x))|(_br_load(p_x+4)))|(_br_load((p_x+4)+4)))|(_br_load(((p_x+4)+4)+4)); + nz = nz|(_br_load((((p_x+4)+4)+4)+4)); + nz = nz|(_br_load(((((p_x+4)+4)+4)+4)+4)); + nz = nz|(_br_load((((((p_x+4)+4)+4)+4)+4)+4)); + nz = nz|(_br_load(((((((p_x+4)+4)+4)+4)+4)+4)+4)); + nz = br_broadcast_nonzero(nz); + return nz; +} + +static inline void u256_shr(br_word_t p_out, br_word_t p_x, br_word_t n) { + br_word_t x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7; + x0 = _br_load(p_x); + x1 = _br_load(p_x+4); + x2 = _br_load((p_x+4)+4); + x3 = _br_load(((p_x+4)+4)+4); + x4 = _br_load((((p_x+4)+4)+4)+4); + x5 = _br_load(((((p_x+4)+4)+4)+4)+4); + x6 = _br_load((((((p_x+4)+4)+4)+4)+4)+4); + x7 = _br_load(((((((p_x+4)+4)+4)+4)+4)+4)+4); + y0 = shrd(x0, x1, n); + y1 = shrd(x1, x2, n); + y2 = shrd(x2, x3, n); + y3 = shrd(x3, x4, n); + y4 = shrd(x4, x5, n); + y5 = shrd(x5, x6, n); + y6 = shrd(x6, x7, n); + y7 = x7>>(n&(sizeof(br_word_t)*8-1)); + _br_store(p_out, y0); + _br_store(p_out+4, y1); + _br_store((p_out+4)+4, y2); + _br_store(((p_out+4)+4)+4, y3); + _br_store((((p_out+4)+4)+4)+4, y4); + _br_store(((((p_out+4)+4)+4)+4)+4, y5); + _br_store((((((p_out+4)+4)+4)+4)+4)+4, y6); + _br_store(((((((p_out+4)+4)+4)+4)+4)+4)+4, y7); +} + +static inline void u256_set_p256_minushalf_conditional(br_word_t p_out, br_word_t mask) { + br_word_t mh0, mh1, mh2, mh3, mh4, mh5, mh6, mh7; + mh0 = 0u-(br_word_t)1; + mh1 = mh0; + mh2 = mh0>>1; + mh3 = (br_word_t)0; + mh4 = (br_word_t)0; + mh5 = (br_word_t)1<<31; + mh6 = mh5; + mh7 = mh2; + _br_store(p_out, mask&mh0); + _br_store(p_out+4, mask&mh1); + _br_store((p_out+4)+4, mask&mh2); + _br_store(((p_out+4)+4)+4, mask&mh3); + _br_store((((p_out+4)+4)+4)+4, mask&mh4); + _br_store(((((p_out+4)+4)+4)+4)+4, mask&mh5); + _br_store((((((p_out+4)+4)+4)+4)+4)+4, mask&mh6); + _br_store(((((((p_out+4)+4)+4)+4)+4)+4)+4, mask&mh7); +} diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/p256_field_64.br.c.inc b/Sources/CCryptoBoringSSL/third_party/fiat/p256_field_64.br.c.inc new file mode 100644 index 000000000..b23246b1c --- /dev/null +++ b/Sources/CCryptoBoringSSL/third_party/fiat/p256_field_64.br.c.inc @@ -0,0 +1,84 @@ +// Generated from Bedrock code in Fiat Cryptography. Avoid editing directly. + +static inline br_word_t shrd(br_word_t lo, br_word_t hi, br_word_t n) { + br_word_t res; + res = lo>>(n&(sizeof(br_word_t)*8-1)); + if (n) { + res = (hi<<((((((0u-(br_word_t)1)>>27)&63)+1)-n)&(sizeof(br_word_t)*8-1)))|res; + } else { + /*skip*/ + } + return res; +} + +static inline void p256_coord_add(br_word_t p_out, br_word_t p_x, br_word_t p_y) { + br_word_t r4, carry, t0, t1, t2, borrow, t3, r0, r1, r2, r3; + carry = br_full_add(_br_load(p_x), _br_load(p_y), (br_word_t)0, &t0); + carry = br_full_add(_br_load(p_x+8), _br_load(p_y+8), carry, &t1); + carry = br_full_add(_br_load((p_x+8)+8), _br_load((p_y+8)+8), carry, &t2); + carry = br_full_add(_br_load(((p_x+8)+8)+8), _br_load(((p_y+8)+8)+8), carry, &t3); + borrow = br_full_sub(t0, (br_word_t)0xffffffffffffffff, (br_word_t)0, &r0); + borrow = br_full_sub(t1, (br_word_t)0xffffffff, borrow, &r1); + borrow = br_full_sub(t2, (br_word_t)0, borrow, &r2); + borrow = br_full_sub(t3, (br_word_t)0xffffffff00000001, borrow, &r3); + borrow = br_full_sub(carry, (br_word_t)0, borrow, &r4); + r0 = br_cmov(borrow, t0, r0); + r1 = br_cmov(borrow, t1, r1); + r2 = br_cmov(borrow, t2, r2); + r3 = br_cmov(borrow, t3, r3); + _br_store(p_out, r0); + _br_store(p_out+8, r1); + _br_store((p_out+8)+8, r2); + _br_store(((p_out+8)+8)+8, r3); +} + +static inline void p256_coord_sub(br_word_t out, br_word_t x, br_word_t y) { + br_word_t borrow, t0, t1, t2, t3, mask, carry, r0, r1, r2, r3; + borrow = br_full_sub(_br_load(x), _br_load(y), (br_word_t)0, &t0); + borrow = br_full_sub(_br_load(x+8), _br_load(y+8), borrow, &t1); + borrow = br_full_sub(_br_load((x+8)+8), _br_load((y+8)+8), borrow, &t2); + borrow = br_full_sub(_br_load(((x+8)+8)+8), _br_load(((y+8)+8)+8), borrow, &t3); + mask = br_value_barrier(0u-borrow); + carry = br_full_add(t0, mask, (br_word_t)0, &r0); + carry = br_full_add(t1, mask&0xffffffff, carry, &r1); + carry = br_full_add(t2, (br_word_t)0, carry, &r2); + carry = br_full_add(t3, mask&0xffffffff00000001, carry, &r3); + _br_store(out, r0); + _br_store(out+8, r1); + _br_store((out+8)+8, r2); + _br_store(((out+8)+8)+8, r3); +} + +static inline br_word_t p256_coord_nonzero(br_word_t p_x) { + br_word_t nz; + nz = br_broadcast_nonzero((((_br_load(p_x))|(_br_load(p_x+8)))|(_br_load((p_x+8)+8)))|(_br_load(((p_x+8)+8)+8))); + return nz; +} + +static inline void u256_shr(br_word_t p_out, br_word_t p_x, br_word_t n) { + br_word_t x0, x1, x2, x3, y0, y1, y2, y3; + x0 = _br_load(p_x); + x1 = _br_load(p_x+8); + x2 = _br_load((p_x+8)+8); + x3 = _br_load(((p_x+8)+8)+8); + y0 = shrd(x0, x1, n); + y1 = shrd(x1, x2, n); + y2 = shrd(x2, x3, n); + y3 = x3>>(n&(sizeof(br_word_t)*8-1)); + _br_store(p_out, y0); + _br_store(p_out+8, y1); + _br_store((p_out+8)+8, y2); + _br_store(((p_out+8)+8)+8, y3); +} + +static inline void u256_set_p256_minushalf_conditional(br_word_t p_out, br_word_t mask) { + br_word_t mh0, mh1, mh2, mh3; + mh0 = 0u-(br_word_t)1; + mh1 = mh0>>((br_word_t)33&(sizeof(br_word_t)*8-1)); + mh2 = mh0<<((br_word_t)63&(sizeof(br_word_t)*8-1)); + mh3 = (mh0<<((br_word_t)32&(sizeof(br_word_t)*8-1)))>>1; + _br_store(p_out, mask&mh0); + _br_store(p_out+8, mask&mh1); + _br_store((p_out+8)+8, mask&mh2); + _br_store(((p_out+8)+8)+8, mask&mh3); +} diff --git a/Sources/CCryptoBoringSSL/third_party/fiat/p256_point.br.c.inc b/Sources/CCryptoBoringSSL/third_party/fiat/p256_point.br.c.inc new file mode 100644 index 000000000..117547bdf --- /dev/null +++ b/Sources/CCryptoBoringSSL/third_party/fiat/p256_point.br.c.inc @@ -0,0 +1,112 @@ +// Generated from Bedrock code in Fiat Cryptography. Avoid editing directly. + +static inline br_word_t br_broadcast_odd(br_word_t x) { + br_word_t y; + x = br_value_barrier(x&1); + y = 0u-x; + return y; +} + +static inline void p256_coord_halve(br_word_t y, br_word_t x) { + br_word_t m, mmh; + uint8_t _br_stackalloc_mmh[32] = {0}; mmh = (br_word_t)&_br_stackalloc_mmh; + m = br_broadcast_odd(_br_load(x)); + u256_set_p256_minushalf_conditional(mmh, m); + u256_shr(y, x, (br_word_t)1); + p256_coord_sub(y, y, mmh); +} + +static inline br_word_t p256_point_iszero(br_word_t p_P) { + br_word_t z, nz; + nz = p256_coord_nonzero((p_P+32)+32); + z = ~nz; + return z; +} + +static inline void p256_point_double(br_word_t out, br_word_t in1) { + br_word_t t2, tmp, A, D; + uint8_t _br_stackalloc_D[32] = {0}; D = (br_word_t)&_br_stackalloc_D; + uint8_t _br_stackalloc_A[32] = {0}; A = (br_word_t)&_br_stackalloc_A; + uint8_t _br_stackalloc_tmp[32] = {0}; tmp = (br_word_t)&_br_stackalloc_tmp; + p256_coord_add(D, in1+32, in1+32); + p256_coord_sqr(tmp, (in1+32)+32); + p256_coord_sqr(D, D); + p256_coord_mul((out+32)+32, (in1+32)+32, in1+32); + p256_coord_add((out+32)+32, (out+32)+32, (out+32)+32); + p256_coord_add(A, in1, tmp); + p256_coord_sub(tmp, in1, tmp); + uint8_t _br_stackalloc_t2[32] = {0}; t2 = (br_word_t)&_br_stackalloc_t2; + p256_coord_add(t2, tmp, tmp); + p256_coord_add(tmp, t2, tmp); + p256_coord_sqr(out+32, D); + p256_coord_mul(A, A, tmp); + p256_coord_mul(D, D, in1); + p256_coord_sqr(out, A); + p256_coord_add(tmp, D, D); + p256_coord_sub(out, out, tmp); + p256_coord_sub(D, D, out); + p256_coord_mul(D, D, A); + p256_coord_halve(out+32, out+32); + p256_coord_sub(out+32, D, out+32); +} + +static inline br_word_t p256_point_add_nz_nz_neq(br_word_t p_out, br_word_t p_P, br_word_t p_Q) { + br_word_t z1z1, z2z2, u1, Hsqr, ok, different_x, different_y, u2, Hcub, s1, r, h, s2; + uint8_t _br_stackalloc_z1z1[32] = {0}; z1z1 = (br_word_t)&_br_stackalloc_z1z1; + uint8_t _br_stackalloc_z2z2[32] = {0}; z2z2 = (br_word_t)&_br_stackalloc_z2z2; + uint8_t _br_stackalloc_u1[32] = {0}; u1 = (br_word_t)&_br_stackalloc_u1; + uint8_t _br_stackalloc_u2[32] = {0}; u2 = (br_word_t)&_br_stackalloc_u2; + uint8_t _br_stackalloc_h[32] = {0}; h = (br_word_t)&_br_stackalloc_h; + uint8_t _br_stackalloc_s1[32] = {0}; s1 = (br_word_t)&_br_stackalloc_s1; + uint8_t _br_stackalloc_s2[32] = {0}; s2 = (br_word_t)&_br_stackalloc_s2; + uint8_t _br_stackalloc_r[32] = {0}; r = (br_word_t)&_br_stackalloc_r; + uint8_t _br_stackalloc_Hsqr[32] = {0}; Hsqr = (br_word_t)&_br_stackalloc_Hsqr; + uint8_t _br_stackalloc_Hcub[32] = {0}; Hcub = (br_word_t)&_br_stackalloc_Hcub; + p256_coord_sqr(z1z1, (p_P+32)+32); + p256_coord_mul(u2, p_Q, z1z1); + p256_coord_sqr(z2z2, (p_Q+32)+32); + p256_coord_mul(u1, p_P, z2z2); + p256_coord_sub(h, u2, u1); + p256_coord_mul(s2, (p_P+32)+32, z1z1); + p256_coord_mul((p_out+32)+32, h, (p_P+32)+32); + p256_coord_mul((p_out+32)+32, (p_out+32)+32, (p_Q+32)+32); + p256_coord_mul(s2, s2, p_Q+32); + p256_coord_mul(s1, (p_Q+32)+32, z2z2); + p256_coord_mul(s1, s1, p_P+32); + p256_coord_sub(r, s2, s1); + p256_coord_sqr(Hsqr, h); + p256_coord_sqr(p_out, r); + p256_coord_mul(Hcub, Hsqr, h); + p256_coord_mul(u2, u1, Hsqr); + different_x = p256_coord_nonzero(Hcub); + different_y = p256_coord_nonzero(p_out); + ok = br_value_barrier(different_x|different_y); + p256_coord_sub(p_out, p_out, Hcub); + p256_coord_sub(p_out, p_out, u2); + p256_coord_sub(p_out, p_out, u2); + p256_coord_sub(h, u2, p_out); + p256_coord_mul(s2, Hcub, s1); + p256_coord_mul(h, h, r); + p256_coord_sub(p_out+32, h, s2); + return ok; +} + +static inline void p256_point_add_vartime_if_doubling(br_word_t p_out, br_word_t p_P, br_word_t p_Q) { + br_word_t p_tmp, zeroP, zeroQ, ok, p_sel; + zeroP = p256_point_iszero(p_P); + zeroQ = p256_point_iszero(p_Q); + uint8_t _br_stackalloc_p_tmp[96] = {0}; p_tmp = (br_word_t)&_br_stackalloc_p_tmp; + ok = p256_point_add_nz_nz_neq(p_tmp, p_P, p_Q); + ok = br_declassify((zeroP|zeroQ)|ok); + uint8_t _br_stackalloc_p_sel[96] = {0}; p_sel = (br_word_t)&_br_stackalloc_p_sel; + br_memset(p_sel, (br_word_t)0, (br_word_t)96); + br_memcxor(p_sel, p_tmp, (br_word_t)96, (~zeroP)&(~zeroQ)); + br_memcxor(p_sel, p_P, (br_word_t)96, (~zeroP)&zeroQ); + br_memcxor(p_sel, p_Q, (br_word_t)96, zeroP&(~zeroQ)); + if (ok) { + /*skip*/ + } else { + p256_point_double(p_sel, p_P); + } + br_memcpy(p_out, p_sel, (br_word_t)96); +} diff --git a/Sources/CryptoBoringWrapper/Util/FiniteFieldArithmeticContext.swift b/Sources/CryptoBoringWrapper/Util/FiniteFieldArithmeticContext.swift index 99078a44d..ec101b5d1 100644 --- a/Sources/CryptoBoringWrapper/Util/FiniteFieldArithmeticContext.swift +++ b/Sources/CryptoBoringWrapper/Util/FiniteFieldArithmeticContext.swift @@ -272,7 +272,7 @@ extension FiniteFieldArithmeticContext { _ p: UnsafePointer?, _ m: UnsafePointer?, _ ctx: OpaquePointer?, - _ mont: UnsafePointer? + _ mont: OpaquePointer? ) -> Int32 ) throws -> ArbitraryPrecisionInteger { var result = ArbitraryPrecisionInteger() @@ -298,7 +298,7 @@ extension FiniteFieldArithmeticContext { /// Some functions require a `BN_MONT_CTX` parameter: this obtains one for the field modulus with a scoped lifetime. fileprivate func withUnsafeBN_MONT_CTX( - _ body: (UnsafePointer) throws -> T + _ body: (OpaquePointer) throws -> T ) rethrows -> T { diff --git a/scripts/generate-linux-sdks.sh b/scripts/generate-linux-sdks.sh index 65cd7bfcb..959bc1197 100755 --- a/scripts/generate-linux-sdks.sh +++ b/scripts/generate-linux-sdks.sh @@ -25,10 +25,10 @@ set -e -SWIFT_VERSION=5.10 +SWIFT_VERSION=6.1.2 DISTRO_NAME=ubuntu -DISTRO_VERSION=jammy -DISTRO_VERSION_GENERATOR=22.04 +DISTRO_VERSION=noble +DISTRO_VERSION_GENERATOR=24.04 TMPDIR=$(mktemp -d /tmp/.workingXXXXXX) function generate_swift_sdk { diff --git a/scripts/patch-3-missing-extern-c.patch b/scripts/patch-3-missing-extern-c.patch new file mode 100644 index 000000000..aeda6890e --- /dev/null +++ b/scripts/patch-3-missing-extern-c.patch @@ -0,0 +1,25 @@ +diff --git a/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h b/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h +index c5a8113..27f8060 100644 +--- a/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h ++++ b/Sources/CCryptoBoringSSL/crypto/fipsmodule/service_indicator/internal.h +@@ -17,6 +17,9 @@ + + #include + ++#if defined(__cplusplus) ++extern "C" { ++#endif + + // FIPS_service_indicator_before_call and |FIPS_service_indicator_after_call| + // both currently return the same local thread counter which is slowly +@@ -37,6 +40,10 @@ + OPENSSL_EXPORT uint64_t FIPS_service_indicator_before_call(void); + OPENSSL_EXPORT uint64_t FIPS_service_indicator_after_call(void); + ++#if defined(__cplusplus) ++} ++#endif ++ + #if defined(BORINGSSL_FIPS) + + // FIPS_service_indicator_update_state records that an approved service has been diff --git a/scripts/vendor-boringssl.sh b/scripts/vendor-boringssl.sh index b4d75ebbb..8fcf540d2 100755 --- a/scripts/vendor-boringssl.sh +++ b/scripts/vendor-boringssl.sh @@ -87,8 +87,8 @@ function mangle_symbols { # Begin by building for macOS. We build for two target triples, Intel # and Apple Silicon. - swift build --triple "x86_64-apple-macosx" --product CCryptoBoringSSL --enable-test-discovery - swift build --triple "arm64-apple-macosx" --product CCryptoBoringSSL --enable-test-discovery + swift build --triple "x86_64-apple-macosx" --product CCryptoBoringSSL + swift build --triple "arm64-apple-macosx" --product CCryptoBoringSSL ( cd "${SRCROOT}" go mod tidy -modcacherw @@ -107,9 +107,9 @@ function mangle_symbols { # Now cross compile for our targets. # NOTE: This requires running the `generate-linux-sdks.sh` script first to generate the Swift SDKs. - swift build --swift-sdk 5.10-RELEASE_ubuntu_jammy_x86_64 --product CCryptoBoringSSL - swift build --swift-sdk 5.10-RELEASE_ubuntu_jammy_aarch64 --product CCryptoBoringSSL - swift build --swift-sdk 5.10-RELEASE_ubuntu_jammy_armv7 --product CCryptoBoringSSL + swift build --swift-sdk 6.1.2-RELEASE_ubuntu_noble_x86_64 --product CCryptoBoringSSL + swift build --swift-sdk 6.1.2-RELEASE_ubuntu_noble_aarch64 --product CCryptoBoringSSL + swift build --swift-sdk 6.1.2-RELEASE_ubuntu_noble_armv7 --product CCryptoBoringSSL # Now we need to generate symbol mangles for Linux. We can do this in # one go for all of them. @@ -147,6 +147,34 @@ function mangle_symbols { namespace_inlines "$DSTROOT" } +function mangle_cpp_structures { + echo "MANGLING C++ structures" + ( + # We need a .a: may as well get SwiftPM to give it to us. + # Temporarily enable the product we need. + $sed -i -e 's/MANGLE_START/MANGLE_START*\//' -e 's/MANGLE_END/\/*MANGLE_END/' "${HERE}/Package.swift" + + # Build for macOS. + swift build --product CCryptoBoringSSL + + # Woah, this is a hell of a command! What does it do? + # + # The nm command grabs all global defined symbols. We then run the C++ demangler over them and look for methods with '::' in them: + # these are C++ methods. We then exclude any that contain CCryptoBoringSSL (as those are already namespaced!) and any that contain swift + # (as those were put there by the Swift runtime, not us). This gives us a list of symbols. The following cut command + # grabs the type name from each of those (the bit preceding the '::'). Then, we sort and uniqify that list. + # Finally, we remove any symbol that ends in std. This gives us all the structures that need to be renamed. + structures=$(nm -gUj "$(swift build --show-bin-path)/libCCryptoBoringSSL.a" | c++filt | grep "::" | grep -v -e "CCryptoBoringSSL" -e "swift" | cut -d : -f1 | grep -v "std$" | $sed -E -e 's/([^<>]*)(<[^<>]*>)?/\1/' | sort | uniq) + + for struct in ${structures}; do + echo "#define ${struct} BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ${struct})" >> "${DSTROOT}/include/CCryptoBoringSSL_boringssl_prefix_symbols.h" + done + + # Remove the product, as we no longer need it. + $sed -i -e 's/MANGLE_START\*\//MANGLE_START/' -e 's/\/\*MANGLE_END/MANGLE_END/' "${HERE}/Package.swift" + ) +} + case "$(uname -s)" in Darwin) sed=gsed @@ -175,10 +203,10 @@ echo "CLONING boringssl" mkdir -p "$SRCROOT" git clone https://boringssl.googlesource.com/boringssl "$SRCROOT" cd "$SRCROOT" -if [ "$BORINGSSL_REVISION" ]; then +if [ "${BORINGSSL_REVISION:-}" ]; then echo "CHECKING OUT boringssl@${BORINGSSL_REVISION}" git checkout "$BORINGSSL_REVISION" -else +else BORINGSSL_REVISION=$(git rev-parse HEAD) echo "CLONED boringssl@${BORINGSSL_REVISION}" fi @@ -200,7 +228,6 @@ echo "GENERATING assembly helpers" PATTERNS=( 'include/openssl/*.h' -'include/openssl/experimental/*.h' 'ssl/*.h' 'ssl/*.cc' 'crypto/*.h' @@ -218,7 +245,7 @@ PATTERNS=( 'gen/bcm/*.S' 'third_party/fiat/*.h' 'third_party/fiat/asm/*.S' -#'third_party/fiat/*.c' +'third_party/fiat/*.c.inc' ) EXCLUDES=( @@ -262,6 +289,11 @@ echo "DISABLING assembly on x86 Windows" ) +# Unfortunately, this patch for an upstream bug which incorrectly leaves C symbol using C++ mangling must be +# applied before we mangle symbols, so we can't place it with the others below. +echo "PATCHING BoringSSL (early)" +git apply "${HERE}/scripts/patch-3-missing-extern-c.patch" + mangle_symbols echo "RENAMING header files" @@ -295,6 +327,10 @@ echo "RENAMING header files" popd ) +echo "PATCHING BoringSSL" +git apply "${HERE}/scripts/patch-1-inttypes.patch" +git apply "${HERE}/scripts/patch-2-more-inttypes.patch" + # We need to avoid having the stack be executable. BoringSSL does this in its build system, but we can't. echo "PROTECTING against executable stacks" ( @@ -303,9 +339,7 @@ echo "PROTECTING against executable stacks" find . -name "*.S" | xargs $sed -i '$ a #if defined(__linux__) && defined(__ELF__)\n.section .note.GNU-stack,"",%progbits\n#endif\n' ) -echo "PATCHING BoringSSL" -git apply "${HERE}/scripts/patch-1-inttypes.patch" -git apply "${HERE}/scripts/patch-2-more-inttypes.patch" +mangle_cpp_structures # We need BoringSSL to be modularised echo "MODULARISING BoringSSL" From b1f7679f29c343ee2df0c61a5abbfd3cab413c77 Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Tue, 16 Sep 2025 11:08:43 -0400 Subject: [PATCH 28/36] Buildfix OpenBSD. (#411) The threading changes missed an `os(OpenBSD)`, causing the Swift toolchain build to fail. ### Checklist - [ ] I've run tests to see all new and existing tests pass - [X] I've followed the code style of the rest of the project - [X] I've read the [Contribution Guidelines](CONTRIBUTING.md) - [ ] I've updated the documentation if necessary #### If you've made changes to `gyb` files - [ ] I've run `./scripts/generate_boilerplate_files_with_gyb.sh` and included updated generated files in a commit of this pull request ### Motivation: Buildfix the upstream Swift toolchain on OpenBSD. ### Modifications: Added an `os(OpenBSD)` conditional, much like FreeBSD. ### Result: The Swift toolchain will build successfully again. --- Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift index 6b2ccdf09..07051a672 100644 --- a/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift +++ b/Sources/_CryptoExtras/Util/ThreadSpecific/ThreadPosix.swift @@ -25,7 +25,7 @@ // //===----------------------------------------------------------------------===// -#if os(Linux) || os(Android) || os(FreeBSD) || canImport(Darwin) +#if os(Linux) || os(Android) || os(FreeBSD) || os(OpenBSD) || canImport(Darwin) #if canImport(Glibc) @preconcurrency import Glibc #elseif canImport(Bionic) From 527fef6228c3ce8a46ebf63e631bd60adf6c4d21 Mon Sep 17 00:00:00 2001 From: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> Date: Mon, 22 Sep 2025 13:02:42 +0200 Subject: [PATCH 29/36] Remove useless `try` to fix warnings (#412) `getKeyPrimitives` is marked as throws but is not actually throwing errors and this is yielding warnings. This fixes the warnings. ### Checklist - [x] I've run tests to see all new and existing tests pass - [x] I've followed the code style of the rest of the project - [x] I've read the [Contribution Guidelines](CONTRIBUTING.md) - [x] I've updated the documentation if necessary #### If you've made changes to `gyb` files - [N/A] I've run `./scripts/generate_boilerplate_files_with_gyb.sh` and included updated generated files in a commit of this pull request ### Motivation: Currently there's a warning ``` /swift-crypto/Sources/_CryptoExtras/RSA/RSA_boring.swift:67:9: warning: no calls to throwing functions occur within 'try' expression ``` because we're using `try` on a non throwing function. This escalates to all of the functions that use it. I'm not sure if removing `throws` from a non-actually-throwing public function is breaking, as using `try` on a non throwing function only yields a warning (if not in warnings-as-errors mode) but it actively is a signature change so it might still be breaking. In case we don't want to merge this as is, the warning can be removed by simply removing useless `try`s and we can wait for the next major version to remove the false-throwers. ### Modifications: Remove the useless `try` and `throws` where they're not needed. ### Result: The warning is gone. --- Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift | 2 +- Sources/_CryptoExtras/RSA/RSA.swift | 4 ++-- Sources/_CryptoExtras/RSA/RSA_boring.swift | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift b/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift index a0af91821..fc69ea7ea 100644 --- a/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift +++ b/Sources/_CryptoExtras/RSA/RSA+BlindSigning.swift @@ -132,7 +132,7 @@ extension _RSA.BlindSigning { } public func getKeyPrimitives() throws -> Primitives { - let (n, e) = try self.backing.getKeyPrimitives() + let (n, e) = self.backing.getKeyPrimitives() return Primitives(modulus: n, publicExponent: e) } } diff --git a/Sources/_CryptoExtras/RSA/RSA.swift b/Sources/_CryptoExtras/RSA/RSA.swift index 642236bf9..88f333988 100644 --- a/Sources/_CryptoExtras/RSA/RSA.swift +++ b/Sources/_CryptoExtras/RSA/RSA.swift @@ -142,7 +142,7 @@ extension _RSA.Signing { } public func getKeyPrimitives() throws -> Primitives { - let (n, e) = try self.backing.getKeyPrimitives() + let (n, e) = self.backing.getKeyPrimitives() return Primitives(modulus: n, publicExponent: e) } } @@ -539,7 +539,7 @@ extension _RSA.Encryption { fileprivate init(_ backing: BackingPublicKey) { self.backing = backing } public func getKeyPrimitives() throws -> Primitives { - let (n, e) = try self.backing.getKeyPrimitives() + let (n, e) = self.backing.getKeyPrimitives() return Primitives(modulus: n, publicExponent: e) } } diff --git a/Sources/_CryptoExtras/RSA/RSA_boring.swift b/Sources/_CryptoExtras/RSA/RSA_boring.swift index 3c6eebbb7..f43c21914 100644 --- a/Sources/_CryptoExtras/RSA/RSA_boring.swift +++ b/Sources/_CryptoExtras/RSA/RSA_boring.swift @@ -63,8 +63,8 @@ internal struct BoringSSLRSAPublicKey: Sendable { self.backing = backing } - func getKeyPrimitives() throws -> (n: Data, e: Data) { - try self.backing.getKeyPrimitives() + func getKeyPrimitives() -> (n: Data, e: Data) { + self.backing.getKeyPrimitives() } } From 95ba0316a9b733e92bb6b071255ff46263bbe7dc Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Mon, 22 Sep 2025 13:22:05 +0100 Subject: [PATCH 30/36] Enable Swift 6.2 jobs in CI (#414) Motivation: Swift 6.2 has been released, we should add it to our CI coverage. Modifications: Add additional Swift 6.2 jobs where appropriate in main.yml, pull_request.yml Result: Improved test coverage. --- .github/workflows/main.yml | 4 ++++ .github/workflows/pull_request.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9e537d8b8..4559640ed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,14 +14,17 @@ jobs: linux_5_10_arguments_override: "--explicit-target-dependency-import-check error" linux_6_0_arguments_override: "--explicit-target-dependency-import-check error" linux_6_1_arguments_override: "--explicit-target-dependency-import-check error" + linux_6_2_arguments_override: "--explicit-target-dependency-import-check error" linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" windows_6_0_enabled: true windows_6_1_enabled: true + windows_6_2_enabled: true windows_nightly_next_enabled: true windows_nightly_main_enabled: true windows_6_0_arguments_override: "--explicit-target-dependency-import-check error" windows_6_1_arguments_override: "--explicit-target-dependency-import-check error" + windows_6_2_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" @@ -31,6 +34,7 @@ jobs: with: windows_6_0_enabled: true windows_6_1_enabled: true + windows_6_2_enabled: true windows_nightly_next_enabled: true windows_nightly_main_enabled: true diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 234445829..4c2ac809d 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -19,14 +19,17 @@ jobs: linux_5_10_arguments_override: "--explicit-target-dependency-import-check error" linux_6_0_arguments_override: "--explicit-target-dependency-import-check error" linux_6_1_arguments_override: "--explicit-target-dependency-import-check error" + linux_6_2_arguments_override: "--explicit-target-dependency-import-check error" linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" windows_6_0_enabled: true windows_6_1_enabled: true + windows_6_2_enabled: true windows_nightly_next_enabled: true windows_nightly_main_enabled: true windows_6_0_arguments_override: "--explicit-target-dependency-import-check error" windows_6_1_arguments_override: "--explicit-target-dependency-import-check error" + windows_6_2_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_next_arguments_override: "--explicit-target-dependency-import-check error" windows_nightly_main_arguments_override: "--explicit-target-dependency-import-check error" @@ -36,6 +39,7 @@ jobs: with: windows_6_0_enabled: true windows_6_1_enabled: true + windows_6_2_enabled: true windows_nightly_next_enabled: true windows_nightly_main_enabled: true From 52668cad85b2f8421d7403c616bd970be1139713 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 22 Sep 2025 14:53:58 +0100 Subject: [PATCH 31/36] Remove unneeded import --- Tests/CryptoExtrasTests/CMACTests.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/CryptoExtrasTests/CMACTests.swift b/Tests/CryptoExtrasTests/CMACTests.swift index ab20113a3..386d906ec 100644 --- a/Tests/CryptoExtrasTests/CMACTests.swift +++ b/Tests/CryptoExtrasTests/CMACTests.swift @@ -15,7 +15,6 @@ import Crypto import CryptoExtras import Foundation import XCTest -import _CryptoExtras final class CMACTests: XCTestCase { // Borrowed from CryptoKit From a5fc067dfb25216a37c30f26bb2d8a88ecfd5f09 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 22 Sep 2025 14:55:32 +0100 Subject: [PATCH 32/36] Fixup extra cryptoextras file --- .../_CryptoExtrasTests/ARC/ARCAPITests.swift | 352 ------------------ 1 file changed, 352 deletions(-) delete mode 100644 Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift diff --git a/Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift b/Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift deleted file mode 100644 index 2a6f0f88b..000000000 --- a/Tests/_CryptoExtrasTests/ARC/ARCAPITests.swift +++ /dev/null @@ -1,352 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2024 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// -import Crypto -@testable import _CryptoExtras -import XCTest - -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -final class ARCAPITests: XCTestCase { - - @available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") - func testVectors() throws { - let data = ARCEncodedTestVector.data(using: .utf8)! - let decoder = JSONDecoder() - let vectors = try decoder.decode([ARCTestVector].self, from: data) - XCTAssert(vectors.count > 0, "No test vectors found") - for vector in vectors { - switch vector.suite { - case "ARCV1-P256": try testVector(vector, using: P256.self) - case "ARCV1-P384": try testVector(vector, using: P384.self) - default: XCTFail("Test vector suite not supported: \(vector.suite)") - } - } - } - - fileprivate func testVector(_ vector: ARCTestVector, using _: Curve.Type = Curve.self) throws { - // [Issuer] Create the server secrets. - let privateKey = try Curve._ARCV1.PrivateKey(rawRepresentation: Data( - hexString: vector.ServerKey.x0 + vector.ServerKey.x1 + vector.ServerKey.x2 + vector.ServerKey.xb - )) - - // [Issuer] Serialize public key to share with client (other serializations may be available). - let publicKeyBytes = privateKey.publicKey.rawRepresentation - - // [CHECK] Public key matches test vector. - XCTAssertEqual( - publicKeyBytes.hexString, - vector.ServerKey.X0 + vector.ServerKey.X1 + vector.ServerKey.X2 - ) - - // [Issuer] Define a request context to share with the client. - let requestContext = try Data(hexString: vector.CredentialRequest.request_context) - - // [Verifier] Define a presentation context and presentation limit (e.g. rate-limit). - let presentationContext = try Data(hexString: vector.Presentation1.presentation_context) - let presentationLimit = 2 - - // [Client] Obtain public key, request context, presentation context, and presentation limit out of band. - _ = (publicKeyBytes, requestContext, presentationContext, presentationLimit) - - // [Client] Obtain public key out of band (other serializations may be available). - let publicKey = try Curve._ARCV1.PublicKey(rawRepresentation: publicKeyBytes) - - // [Client] Prepare a credential request using fixed values from test vector. - let precredential = try publicKey.prepareCredentialRequest( - requestContext: requestContext, - m1: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.m1)), - r1: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.r1)), - r2: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialRequest.r2)) - ) - - // [Client -> Issuer] Send the credential request. - let credentialRequestBytes = precredential.credentialRequest.rawRepresentation - - // [CHECK] Credential request scalars match test vector. - XCTAssertEqual( - credentialRequestBytes[..<(2 * Curve.compressedx962PointByteCount)].hexString, - vector.CredentialRequest.m1_enc + vector.CredentialRequest.m2_enc - ) - - // [Issuer] Receive the credential request. - let credentialRequest = try Curve._ARCV1.CredentialRequest(rawRepresentation: credentialRequestBytes) - - // [Issuer] Generate a credential response with fixed value from test vector. - let credentialResponse = try privateKey.issue( - credentialRequest, - b: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.CredentialResponse.b)) - ) - - // [Issuer -> Client] Send the credential response. - let credentialResponseBytes = credentialResponse.rawRepresentation - - // [CHECK] Credential response scalars match test vector, excluding proof. - XCTAssertEqual( - credentialResponseBytes[..<(6 * Curve.compressedx962PointByteCount)].hexString, - vector.CredentialResponse.U - + vector.CredentialResponse.enc_U_prime - + vector.CredentialResponse.X0_aux - + vector.CredentialResponse.X1_aux - + vector.CredentialResponse.X2_aux - + vector.CredentialResponse.H_aux - ) - - // [Client] Receive the credential response. - let _ = try Curve._ARCV1.CredentialResponse(rawRepresentation: credentialResponseBytes) - - // [Client] Generate a credential. - var credential = try publicKey.finalize(credentialResponse, for: precredential) - - // [CHECK] Credential matches test vector. - XCTAssertEqual(credential.backing.U.oprfRepresentation.hexString, vector.Credential.U) - XCTAssertEqual(credential.backing.UPrime.oprfRepresentation.hexString, vector.Credential.U_prime) - XCTAssertEqual(credential.backing.X1.oprfRepresentation.hexString, vector.Credential.X1) - XCTAssertEqual(credential.backing.m1.rawRepresentation.hexString, vector.Credential.m1) - - // [Client] Make a presentation from the credential for a presentation prefix. - let (presentation, _) = try credential.makePresentation( - context: presentationContext, - presentationLimit: presentationLimit, - fixedNonce: Int(vector.Presentation1.nonce.dropFirst(2), radix: 16)!, - a: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.a)), - r: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.r)), - z: Curve._ARCV1.H2G.G.Scalar(bytes: Data(hexString: vector.Presentation1.z)) - ) - - // NOTE: The presentation proof depends on randomly generated blinding factors. This layer doesn't expose - // internal methods for fixing these values - // - // Here, we'll check that the presentation, excluding the proof, with the fixed scalars and nonce, matches - // the presentation from the test vector. - // - // Then, for the remainder of this test, we'll cut over to the presentation from the test vector. - // - // Proof generation and verification, in general, is well covered by other tests; and proof validity, for - // ARC specifically, is covered in the end-to-end tests in ARCPublicAPITests. - - // [CHECK]: Check presentation (excluding proof) matches test vector. - XCTAssertEqual(presentation.backing.U.oprfRepresentation.hexString, vector.Presentation1.U) - XCTAssertEqual(presentation.backing.UPrimeCommit.oprfRepresentation.hexString, vector.Presentation1.U_prime_commit) - XCTAssertEqual(presentation.backing.m1Commit.oprfRepresentation.hexString, vector.Presentation1.m1_commit) - XCTAssertEqual(presentation.backing.tag.oprfRepresentation.hexString, vector.Presentation1.tag) - - // [CHECK]: Serialization of presentation (ecluding proof) matches spec. - XCTAssertEqual( - presentation.rawRepresentation[..<(4 * Curve.compressedx962PointByteCount)].hexString, - vector.Presentation1.U - + vector.Presentation1.U_prime_commit - + vector.Presentation1.m1_commit - + vector.Presentation1.tag - ) - XCTAssertEqual( - presentation.rawRepresentation[(4 * Curve.compressedx962PointByteCount)...].hexString.count, - vector.Presentation1.proof.count - ) - - // [CHECK]: Full serialization of presentation, including proof from test vector, matches test vector. - let testVectorPresentationBytes = try Data( - hexString: vector.Presentation1.U - + vector.Presentation1.U_prime_commit - + vector.Presentation1.m1_commit - + vector.Presentation1.tag - + vector.Presentation1.proof - ) - XCTAssertEqual( - try Curve._ARCV1.Presentation(rawRepresentation: testVectorPresentationBytes).rawRepresentation.hexString, - testVectorPresentationBytes.hexString - ) - - // [Verifier] Receive the presentation (and the nonce, out of band). - let receivedPresentation = try Curve._ARCV1.Presentation(rawRepresentation: testVectorPresentationBytes) - let nonce = Int(vector.Presentation1.nonce.dropFirst(2), radix: 16)! - - // [Verifier] Verify the presentation. - let validPresentation = try privateKey.verify( - receivedPresentation, - requestContext: requestContext, - presentationContext: presentationContext, - presentationLimit: presentationLimit, - nonce: nonce - ) - XCTAssertTrue(validPresentation) - } -} - -// MARK: - Fileprivate protocols to create a unified test over the ARC curves. - -fileprivate protocol ARCCredentialRequest { - init(rawRepresentation: some DataProtocol) throws - var rawRepresentation: Data { get } -} - -fileprivate protocol ARCCredentialResponse { - init(rawRepresentation: some DataProtocol) throws - var rawRepresentation: Data { get } -} - -@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -fileprivate protocol ARCPresentation { - associatedtype H2G: HashToGroup - var backing: ARC.Presentation { get } - init(rawRepresentation: some DataProtocol) throws - var rawRepresentation: Data { get } -} - -@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -fileprivate protocol ARCCredential { - associatedtype H2G: HashToGroup - associatedtype Presentation: ARCPresentation - var backing: ARC.Credential { get } - mutating func makePresentation( - context: some DataProtocol, - presentationLimit: Int, - fixedNonce: Int?, - a: H2G.G.Scalar, - r: H2G.G.Scalar, - z: H2G.G.Scalar - ) throws -> (presentation: Presentation, nonce: Int) - mutating func makePresentation(context: some DataProtocol, presentationLimit: Int) throws -> (presentation: Presentation, nonce: Int) -} - -@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -fileprivate protocol ARCPrivateKey { - associatedtype H2G: HashToGroup - associatedtype Credential - associatedtype PublicKey: ARCPublicKey - associatedtype CredentialRequest: ARCCredentialRequest - associatedtype CredentialResponse: ARCCredentialResponse - associatedtype Presentation: ARCPresentation - init(rawRepresentation: some DataProtocol) throws - var rawRepresentation: Data { get } - var publicKey: PublicKey { get } - func issue(_ credentialRequest: CredentialRequest, b: H2G.G.Scalar) throws -> CredentialResponse - func verify( - _: Presentation, - requestContext: some DataProtocol, - presentationContext: some DataProtocol, - presentationLimit: Int, - nonce: Int - ) throws -> Bool -} - -@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -fileprivate protocol ARCPublicKey { - associatedtype H2G: HashToGroup - associatedtype Precredential: ARCPrecredential - associatedtype CredentialResponse: ARCCredentialResponse - associatedtype Credential: ARCCredential - init(rawRepresentation: some DataProtocol) throws - var rawRepresentation: Data { get } - func prepareCredentialRequest(requestContext: some DataProtocol, m1: H2G.G.Scalar, r1: H2G.G.Scalar, r2: H2G.G.Scalar) throws -> Precredential - func prepareCredentialRequest(requestContext: some DataProtocol) throws -> Precredential - func finalize(_ credentialResponse: CredentialResponse, for precredential: Precredential) throws -> Credential -} - -fileprivate protocol ARCPrecredential { - associatedtype CredentialRequest: ARCCredentialRequest - var credentialRequest: CredentialRequest { get } -} - -@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -fileprivate protocol ARCV1 { - associatedtype H2G: HashToGroup - associatedtype CredentialRequest: ARCCredentialRequest - associatedtype CredentialResponse: ARCCredentialResponse - associatedtype Presentation: ARCPresentation - associatedtype Credential: ARCCredential - associatedtype PrivateKey: ARCPrivateKey - associatedtype PublicKey: ARCPublicKey -} - -@available(macOS 10.15, iOS 13.2, tvOS 13.2, watchOS 6.1, macCatalyst 13.2, visionOS 1.2, *) -fileprivate protocol ARCCurve: OpenSSLSupportedNISTCurve { - associatedtype H2G: HashToGroup where H2G == OpenSSLHashToCurve - associatedtype _ARCV1: ARCV1 -} - -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1.Precredential: ARCPrecredential {} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1.CredentialRequest: ARCCredentialRequest {} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1.CredentialResponse: ARCCredentialResponse {} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1.Credential: ARCCredential {} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1.Presentation: ARCPresentation {} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1.PublicKey: ARCPublicKey { - typealias H2G = P256._ARCV1.H2G -} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1.PrivateKey: ARCPrivateKey {} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256._ARCV1: ARCV1 {} -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P256: ARCCurve {} - - -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1.Precredential: ARCPrecredential {} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1.CredentialRequest: ARCCredentialRequest {} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1.CredentialResponse: ARCCredentialResponse {} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1.Credential: ARCCredential {} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1.Presentation: ARCPresentation {} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1.PublicKey: ARCPublicKey { - typealias H2G = P384._ARCV1.H2G -} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1.PrivateKey: ARCPrivateKey {} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384._ARCV1: ARCV1 {} -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -extension P384: ARCCurve {} - - -// Swift 5.10 compiler needs a little more help to infer the conformances. -#if swift(<6.0) -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -fileprivate extension P256._ARCV1.PrivateKey { - typealias H2G = P256._ARCV1.H2G - typealias Credential = P256._ARCV1.Credential - typealias PublicKey = P256._ARCV1.PublicKey - typealias CredentialRequest = P256._ARCV1.CredentialRequest - typealias CredentialResponse = P256._ARCV1.CredentialResponse - typealias Presentation = P256._ARCV1.Presentation -} - -@available(*, deprecated, message: "ARC(P-384) has been removed from the IETF draft; use ARC(P-256) instead.") -@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, macCatalyst 16.0, visionOS 2.0, *) -fileprivate extension P384._ARCV1.PrivateKey { - typealias H2G = P384._ARCV1.H2G - typealias Credential = P384._ARCV1.Credential - typealias PublicKey = P384._ARCV1.PublicKey - typealias CredentialRequest = P384._ARCV1.CredentialRequest - typealias CredentialResponse = P384._ARCV1.CredentialResponse - typealias Presentation = P384._ARCV1.Presentation -} -#endif From 635e176ddce3d999388fd374b042b21533da09a6 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 22 Sep 2025 14:58:05 +0100 Subject: [PATCH 33/36] Return this test file --- .../BoringSSL/ECToolboxBoringSSLTests.swift | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Tests/CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift diff --git a/Tests/CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift b/Tests/CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift new file mode 100644 index 000000000..0bb98375c --- /dev/null +++ b/Tests/CryptoExtrasTests/ECToolbox/BoringSSL/ECToolboxBoringSSLTests.swift @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2025 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import Foundation +import XCTest + +#if !canImport(Darwin) || canImport(CryptoKit, _version: 241.100.42) +// Corresponds to the CryptoKit in XCode 16.3, which has Sendable annotations +import Crypto +@testable import CryptoExtras +#else +@preconcurrency import Crypto +@testable import CryptoExtras +#endif + +final class ECToolboxBoringSSLTests: XCTestCase { + func testThreadLocalFFAC() async { + await testThreadLocalFFAC(P256.self) + await testThreadLocalFFAC(P384.self) + await testThreadLocalFFAC(P521.self) + } + + func testThreadLocalFFAC(_ Curve: (some OpenSSLSupportedNISTCurve & Sendable).Type) async { + let numThreads = 3 + let numReadsPerThread = 2 + + var threads: + [( + thread: Thread, + thisThreadDidReads: XCTestExpectation, + allThreadsDidReads: XCTestExpectation, + thisThreadFinished: XCTestExpectation + )] = [] + + let objectIdentifiers: LockedBox<[(threadID: Int, ffacID: ObjectIdentifier)]> = .init(initialValue: []) + + for i in 1...numThreads { + let thisThreadDidReads = expectation(description: "this thread did its reads") + let allThreadsDidReads = expectation(description: "all threads did their reads") + let thisThreadFinished = expectation(description: "this thread is finished") + let thread = Thread { + for _ in 1...numReadsPerThread { + objectIdentifiers.withLockedValue { + $0.append((i, ObjectIdentifier(Curve.__ffac))) + } + } + thisThreadDidReads.fulfill() + XCTWaiter().wait(for: [allThreadsDidReads], timeout: .greatestFiniteMagnitude) + thisThreadFinished.fulfill() + } + thread.name = "thread-\(i)" + threads.append((thread, thisThreadDidReads, allThreadsDidReads, thisThreadFinished)) + thread.start() + } + await fulfillment(of: threads.map(\.thisThreadDidReads), timeout: 0.5) + for thread in threads { thread.allThreadsDidReads.fulfill() } + await fulfillment(of: threads.map(\.thisThreadFinished), timeout: 0.5) + + objectIdentifiers.withLockedValue { objectIdentifiers in + XCTAssertEqual(objectIdentifiers.count, numThreads * numReadsPerThread) + for threadID in 1...numThreads { + let partitionBoundary = objectIdentifiers.partition(by: { $0.threadID == threadID }) + let otherThreadsObjIDs = objectIdentifiers[..: @unchecked Sendable { + private let lock: NSLock + private var value: Value + + init(initialValue: Value) { + self.value = initialValue + self.lock = NSLock() + } + + func withLockedValue(_ body: (inout Value) throws -> ReturnType) rethrows -> ReturnType { + self.lock.lock() + defer { + self.lock.unlock() + } + return try body(&self.value) + } +} From aae5ab7f51c7ef3797e3a7e3abd24ea2870644a5 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 22 Sep 2025 16:21:29 +0100 Subject: [PATCH 34/36] Re-add missing exports file --- Sources/_CryptoExtras/Exports.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Sources/_CryptoExtras/Exports.swift diff --git a/Sources/_CryptoExtras/Exports.swift b/Sources/_CryptoExtras/Exports.swift new file mode 100644 index 000000000..8423e7c02 --- /dev/null +++ b/Sources/_CryptoExtras/Exports.swift @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftCrypto open source project +// +// Copyright (c) 2019 Apple Inc. and the SwiftCrypto project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_exported import CryptoExtras From 23f7e74502170af893a6fe6b54f165006871f123 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 22 Sep 2025 16:21:56 +0100 Subject: [PATCH 35/36] Remove the incorrectly moved exports --- Sources/CryptoExtras/Exports.swift | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 Sources/CryptoExtras/Exports.swift diff --git a/Sources/CryptoExtras/Exports.swift b/Sources/CryptoExtras/Exports.swift deleted file mode 100644 index 8423e7c02..000000000 --- a/Sources/CryptoExtras/Exports.swift +++ /dev/null @@ -1,15 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftCrypto open source project -// -// Copyright (c) 2019 Apple Inc. and the SwiftCrypto project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftCrypto project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -@_exported import CryptoExtras From f52fa594225aa6dbfaf7cd5f91774435dc046cda Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Mon, 22 Sep 2025 16:35:19 +0100 Subject: [PATCH 36/36] Missing header files --- Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h | 2 ++ scripts/vendor-boringssl.sh | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h index 32403a1ba..7b5a35ab2 100644 --- a/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h +++ b/Sources/CCryptoBoringSSL/include/CCryptoBoringSSL.h @@ -45,6 +45,8 @@ #include "CCryptoBoringSSL_hrss.h" #include "CCryptoBoringSSL_md4.h" #include "CCryptoBoringSSL_md5.h" +#include "CCryptoBoringSSL_mldsa.h" +#include "CCryptoBoringSSL_mlkem.h" #include "CCryptoBoringSSL_obj_mac.h" #include "CCryptoBoringSSL_objects.h" #include "CCryptoBoringSSL_opensslv.h" diff --git a/scripts/vendor-boringssl.sh b/scripts/vendor-boringssl.sh index 3b42740e5..324099fe8 100755 --- a/scripts/vendor-boringssl.sh +++ b/scripts/vendor-boringssl.sh @@ -391,6 +391,8 @@ cat << EOF > "$DSTROOT/include/CCryptoBoringSSL.h" #include "CCryptoBoringSSL_hrss.h" #include "CCryptoBoringSSL_md4.h" #include "CCryptoBoringSSL_md5.h" +#include "CCryptoBoringSSL_mldsa.h" +#include "CCryptoBoringSSL_mlkem.h" #include "CCryptoBoringSSL_obj_mac.h" #include "CCryptoBoringSSL_objects.h" #include "CCryptoBoringSSL_opensslv.h"