Giter Site home page Giter Site logo

swift-jwt's Introduction

Kitura

APIDoc Build Status - Master macOS Linux Apache 2 Slack Status

SwiftJWT

An implementation of JSON Web Token using Swift. JWTs offer a lightweight and compact format for transmitting information between parties, and the information can be verified and trusted due to JWTs being digitally signed.

For more information on JSON Web Tokens, their use cases and how they work, we recommend visiting jwt.io.

Reminder: JWTs sent as JWS do not encrypt data, so never send anything sensitive or confidential in a JWT. This library does not currently support JWE.

Swift version

The latest version of Swift-JWT requires Swift 5.2 or later. You can download this version of the Swift binaries by following this link. Compatibility with other Swift versions is not guaranteed.

Usage

Swift Package Manager

Add dependencies

Add the Swift-JWT package to the dependencies within your application’s Package.swift file. Substitute "x.x.x" with the latest Swift-JWT release.

.package(url: "https://github.com/Kitura/Swift-JWT.git", from: "x.x.x")

Add SwiftJWT to your target's dependencies:

.target(name: "example", dependencies: ["SwiftJWT"]),

Import package

import SwiftJWT

Cocoapods

To include Swift-JWT in a project using CocoaPods, add SwiftJWT to your Podfile:

pod 'SwiftJWT'

Getting Started

The JWT model

In its compact form, a JSON Web Tokens consist of three sections of Base64Url encoded JSON, separated by dots (.).
These section are: Headers, Claims and the Signature. Therefore, a JWT typically looks like the following: xxxxx.yyyyy.zzzzz

Header

The Header struct contains the fields of the JSON Web Token header as defined by RFC7515.
The "typ" header will default to "JWT". The "alg" header will be set to the algorithm name when you sign the JWT.
The other Header fields can be set when initializing the Header or by changing them directly on the Header object.

let myHeader = Header(kid: "KeyID1")

Claims

Claims are statements about an entity (typically, the user) and additional data. The Claims are defined by creating a Swift type that conforms to the Claims protocol. The fields of this type represent the information that will be shared using the JWT.

A list of recommended claims is defined in RFC7519.

struct MyClaims: Claims {
    let iss: String
    let sub: String
    let exp: Date
    let admin: Bool
}
let myClaims = MyClaims(iss: "Kitura", sub: "John", exp: Date(timeIntervalSinceNow: 3600), admin: true)
ClaimsExamples

This library includes some example Claims structs as defined by their online specifications:

  • ClaimsStandardJWT as defined in RFC7519.
  • ClaimsMicroProfile as defined here.
  • ClaimsOpenID.swift as defined here.

JWT

The JWT struct represents the Header and Claims of a JSON Web Token.
You can initialize a JWT by decoding a JWT String, or by providing the JWT Header and Claims.

let myJWT = JWT(header: myHeader, claims: myClaims)

Signing and Verifying JSON web tokens

Creating public and private keys

To sign and verify a JWT using an RSA algorithm, you must provide a public and private key. This could be the contents of a .key file generated via the following Terminal commands:

$ ssh-keygen -t rsa -b 4096 -m PEM -f privateKey.key
# Don't add a passphrase
$ openssl rsa -in privateKey.key -pubout -outform PEM -out privateKey.key.pub

This will create a public and private key pair on your system, and the contents of the private key can be passed into a Swift variable using the following code:

let privateKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/privateKey.key"))
let privateKey: Data = try Data(contentsOf: privateKeyPath, options: .alwaysMapped)
let publicKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/publicKey.key"))
let publicKey: Data = try Data(contentsOf: publicKeyPath, options: .alwaysMapped)

For details on creating elliptic curve public and private keys, view the BlueECC README.txt.

Sign a JWT using a JWTSigner

The struct JWTSigner contains the algorithms that can be used to sign a JWT.

Initialize a JWTSigner using the static function corresponding to the desired RSA algorithm:

let jwtSigner = JWTSigner.rs256(privateKey: privateKey)

To generate a signed JWT string, call the sign function on your JWT instance, passing in a JWTSigner:

let signedJWT = try myJWT.sign(using: jwtSigner)

The resulting signedJWT will be a String of the form:

<encoded header>.<encoded claims>.<signature>

Note: The sign function sets the alg (algorithm) field of the header.

Verify a JWT using JWTVerifier

The struct JWTVerifier contains the algorithms that can be used to verify a JWT.

Initialize a JWTVerifier using the static function corresponding to the desired RSA algorithm:

let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)

To verify a signed JWT string, call the static verify function, passing in your JWT string and the JWTVerifier:

let verified = JWT<MyClaims>.verify(signedJWT, using: jwtVerifier)

The verified field will be a bool that is true if the signature is verified.

Supported Algorithms

The supported algorithms for signing and verifying JWTs are:

  • RS256 - RSASSA-PKCS1-v1_5 using SHA-256
  • RS384 - RSASSA-PKCS1-v1_5 using SHA-384
  • RS512 - RSASSA-PKCS1-v1_5 using SHA-512
  • HS256 - HMAC using using SHA-256
  • HS384 - HMAC using using SHA-384
  • HS512 - HMAC using using SHA-512
  • ES256 - ECDSA using using SHA-256 and a P-256 curve
  • ES384 - ECDSA using using SHA-384 and a P-384 curve
  • ES512 - ECDSA using using SHA-512 and a P-521 curve
  • PS256 - RSA-PSS using SHA-256
  • PS384 - RSA-PSS using SHA-384
  • PS512 - RSA-PSS using SHA-512
  • none - Don't sign or verify the JWT

Note: ECDSA and RSA-PSS algorithms require a minimum Swift version of 4.1.

Validate claims

The validateClaims function validates the standard Date claims of a JWT instance. The following claims are validated if they are present in the Claims object:

  • exp (expiration date)
  • nbf (not before date)
  • iat (issued at date)

The method returns ValidateClaimsResult - an struct that list the various reasons for validation failure. If the validation succeeds ValidateClaimsResult.success is returned. The leeway parameter is the TimeInterval in seconds that a standard Date claim will be valid outside of the specified time. This can be used to account for clock skew between issuers and verifiers.

let validationResult = verified.validateClaims(leeway: 10)
if validationResult != .success {
    print("Claims validation failed: ", validationResult)
}

Decode a JWT from a JWT string

A JWT struct can be initialized from a JWT string. If a JWTVerifier is provided it will be used to verify the signature before initialization

let newJWT = try JWT<MyClaims>(jwtString: signedJWT, verifier: jwtVerifier)

JWTEncoder and JWTDecoder

The JWTEncoder and JWTDecoder classes encode and decode JWT Strings using the same API as JSONEncoder and JSONDecoder:

 let jwtEncoder = JWTEncoder(jwtSigner: jwtSigner)
 let jwtString = try jwtEncoder.encodeToString(myJWT)

 let jwtDecoder = JWTDecoder(jwtVerifier: jwtVerifier)
 let jwt = try jwtDecoder.decode(JWT<MyClaims>.self, fromString: jwtString)

Because JWTEncoder and JWTDecoder conform to KituraContract's BodyEncoder and BodyDecoder protocols, they can be used as a custom coder in Codable routes for sending and receiving JWTs:

 router.encoders[MediaType(type: .application, subType: "jwt")] = { return jwtEncoder }
 router.decoders[MediaType(type: .application, subType: "jwt")] = { return jwtDecoder }

This allows for the use of JWT's in information exchange. By sending and receiving JWT's you can ensure the sending is who they say they are and verify the content hasn't been tampered with.

API Documentation

For more information visit our API reference.

Community

We love to talk server-side Swift, and Kitura. Join our Slack to meet the team!

License

This library is licensed under Apache 2.0. Full license text is available in LICENSE.

swift-jwt's People

Contributors

andrew-lees11 avatar bluk avatar dannys42 avatar devmaximilian avatar djones6 avatar e0 avatar hellerphilipp avatar ianpartridge avatar irar2 avatar kyemaloy97 avatar lukabratos avatar marcocanc avatar mbarnach avatar redryerye avatar wcrestfield avatar zntfdr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swift-jwt's Issues

Token creation fails on ubuntu but not macOS

Hi, I have a Swift command line app that writes to Firebase Firestore after generating a JWT for a service account and works fine on macOS, but as I'm porting it to Ubuntu to run it under systemctl I'm failing to successfully generate the token. Its always returning nil. I thought at first that it may be because the key had a trailing \n but removing that doesn't seem to help. Any assistance would be appreciated.

func constructJWT() throws -> String? {
        //TODO:  get the private kay location from an env variable.
        let myKeyPath: URL
        #if os(macOS)
            myKeyPath = URL.init(fileURLWithPath: "/Users/USERNAME/development/Firebase_RSA.privatekey")
        #endif
        #if os(Linux)
            myKeyPath = URL.init(fileURLWithPath: "/home/USERNAME/development//Firebase_RSA.privatekey")
        #endif
        var key: Data = try Data(contentsOf: myKeyPath, options: .alwaysMapped)
        var keyString = String(data: key, encoding: .utf8)
        print(keyString)
        if let str = keyString, str.last == "\n" {
            keyString = String(str.dropLast())
            if let keyData = keyString?.data(using: .utf8) {
                key =  keyData
            }
            print("Drop trailing return")
            print("Key:  ", keyString)
        }

        let header = Header([.typ:"JWT", .alg:"rsa256"])
        
        let issuedTime = Date()
        let timeToLive: TimeInterval = tokenDuration
        let expirationTime = issuedTime.addingTimeInterval(timeToLive)
        
        let claimsDict: [String:Any] = [ClaimKeys.iss.rawValue:"firebase-....gserviceaccount.com",
                                        "scope":"https://www.googleapis.com/auth/datastore",
                                        ClaimKeys.aud.rawValue:"https://www.googleapis.com/oauth2/v4/token",
                                        ClaimKeys.iat.rawValue:Int(issuedTime.timeIntervalSince1970),
                                        ClaimKeys.exp.rawValue:Int(expirationTime.timeIntervalSince1970)]
        
        let claims = Claims(claimsDict)
        
        var jwt = JWT(header: header, claims: claims)
        let signedJWT: String? = try jwt.sign(using: .rs256(key, .privateKey))
        print("Signed Token:  ", signedJWT)
        return signedJWT
    }

project lacks a clear installation process

I am not clear how to use this project.

I tried installing from pod, based on a comment in a different issue, but this is giving me "Could not build Objective-C module 'SwiftJWT'" with no clear reason why.

There's probably something simple to do here.. but without clear instructions, .. basically only members of the project are likely prepared to use the project. This should of course be resolved!

Many dependency and increase app size

dependencies: [
        .package(url: "https://github.com/Kitura/BlueRSA.git", from: "1.0.200"),
        .package(url: "https://github.com/Kitura/BlueCryptor.git", from: "2.0.1"),
        .package(url: "https://github.com/Kitura/BlueECC.git", from: "1.1.0"),
        .package(url: "https://github.com/Kitura/LoggerAPI.git", from: "1.7.0"),
        .package(url: "https://github.com/Kitura/KituraContracts.git", from: "1.2.200")
    ],

why it should have these many dependency???
i think does not require

also after uploaded my app to appstore, its size increased from 19.7 to 20.4 MB!!!!
do you think it is normal?

Apple Music Sample

I've been trying to get IBM JWT to work with Apple music api. Swift-JWT creates an invalid signature. Do you have sample code that actually auths with apple music?

JWTEncoder/JWTDecoder JWT

You can use JSON Web tokens for information exchange. When doing this the body of the request is encoded as a JSON web token.
We would like to be able so send and retrieve JWT in the body of Codable routes.
We believe the best approach to achieve this is to create a JWTEncoder/JWTDecoder which could be used for the content type "application/jwt" to encode and decode the body between JWT and Codable types.

As part of the our JWT struct would need to be made Codable.
There is a PR for Codable JWT here
There is a follow on PR for JWTEncoder/decoder here

Release build fails execution

When I integrate SwiftJWT into my App Store Connect CLI tool asc (included in the Assist repo) using Swift Package Manager I get the following runtime error:

objc[57587]: Class _TtGCs18_DictionaryStorageaSo11CFStringRefS0__$ is implemented in both /usr/lib/swift/libswiftCore.dylib (0x7fff9773bfb0) and /usr/lib/swift/libswiftCore.dylib (0x7fff9773c2c8). One of the two will be used. Which one is undefined.
Fatal error: invalid unsafeDowncast: file /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.8.25.8/swift/stdlib/public/core/Builtin.swift, line 235
[1]    57587 illegal hardware instruction  mint run blackjacx/assist@develop asc

To reproduce this:

  1. Clone repo: git clone [email protected]:Blackjacx/Assist.git && cd Assist
  2. Build and run in release mode: swift run -c release asc

Alternatively you can use mint to run (which compiles the package in release mode):
mint run blackjacx/assist.git@develop asc

When I enter swift run asc in the locally checked out folder it works without problems. The difference is, that this time it is compiled in debug mode. When using another JWT library I can confirm that it works with another JWT library so SwiftJWT must be the reason for this.

Find my package manifest file at Package.swift.

Help very appreciated 👍

Header flexibility

Hi there,

I have made local modifications (hacks) to support headers of the type

{
  "alg": "PS256",
  "typ": "JOSE",
  "kid": "xxx",
  "b64": false,
  "http://openbanking.org.uk/iat": 1573333614,
  "http://openbanking.org.uk/iss": "yyy/zzz",
  "http://openbanking.org.uk/tan": "openbanking.org.uk",
  "crit": [
    "b64",
    "http://openbanking.org.uk/iat",
    "http://openbanking.org.uk/iss",
    "http://openbanking.org.uk/tan"
  ]
}

but wondering if these could be supported in the library?

Maybe making headers a Swift protocol is the way to go?

Interested in your thoughts.

BR,
Mark

Make func base64urlEncodedString() public?

When conforming to Claims protocol, it's quite useful to define encode(). In the default implementation of encode() (https://github.com/IBM-Swift/Swift-JWT/blob/master/Sources/SwiftJWT/Claims.swift#L78-L83), a custom Base-64 decoder is called via base64urlEncodedString() but this is not public so inaccessible for user implementations of encode().

If this custom implementation of Base-64 encoding is useful generally, should it be public so user implementations of encode can use it?

How to compile for iOS

Guys, I'm not expert in compiling C libraries. Can you update documentation on how to compile it for iOS?

Is it possible to sign the JWTtoken with a secret key, not private/public keys?

My application doesn't need a public private key to sign an Authentication token, it only needs to sign it with a secret key (String) only know by server and client. Is it possible to implement that in the Swift-JWT as well.

An example of java client to generate my token looks like.

String secret = "whatEver"; 
String token = Jwts.builder().setHeaderParam(Header.TYPE, Header.JWT_TYPE).setClaims(claims)
				.signWith(SignatureAlgorithm.HS256, secret.getBytes()).compact();```

Update release on cocoapods

I cannot install last 3.6.0 and 3.6.1 with Pods, i am lock on the 3.5.3 :(

i use " pod 'SwiftJWT'", i already made a "pod repo update", and if i use "pod 'SwiftJWT', '3.6.1'" i get this error :
[!] CocoaPods could not find compatible versions for pod "SwiftJWT"

there are mention of the version on https://cocoapods.org/pods/SwiftJWT
Are you sure that is upToDate ?

Support ES256, ES384, and ES512

Long shot here, but what are the odds that this can support ECDSA signatures without depending on Apple platforms? This is important for many applications which need to interact with Apple's cloud services (i.e., APNS, MusicKit, etc.).

In investigating this issue myself, it looks like it's at least somewhat straightforward to accomplish this using Apple's Security, but Security obviously isn't available on Linux. Crypto stuff is way over my head and I'm worried that I can't implement it properly working alone, and it seems like there's no Swift library out there yet that handles ECDSA signing without depending on Security. Without that, any such solution is dead on arrival for many server-side use cases which need to run on Linux.

There does exist a crypto library which claims to handle ECDSA signing, but in my experience it doesn't work as expected.

So, how hard would it be to pull this off? I'd be happy to help where I can, even if it's just contributing to inline docs since as I mentioned, proper implementation is important of course, and I'm more than a little worried that I can't do it right by myself.

"Alg" header not settable?

Hi there,

Just curious why alg seems hard-coded to nil in Header class (https://github.com/IBM-Swift/Swift-JWT/blob/master/Sources/SwiftJWT/Header.swift)? I am experimenting with this library for UK Open Banking client registration where I need to set this value (see example Python code for this use case in 4.1.1 here: https://openbanking.atlassian.net/wiki/spaces/DZ/pages/313918598/Integrating+a+TPP+with+Ozone+Model+Banks+Using+Postman+on+Directory+Sandbox

Many thanks for any help!

BR,
Mark

Not usable as dependency for another Framework

I cannot use Swift-JWT as dependency for another framework - integration via SMP. I get the following error:

${HOME}/dev/projects/private/Assist/.build/x86_64-apple-macosx/debug/SwiftJWT.build/module.modulemap:2:12: error: header '${HOME}/dev/projects/private/Assist/.build/x86_64-apple-macosx/debug/SwiftJWT.build/SwiftJWT-Swift.h' not found
    header "${HOME}/dev/projects/private/Assist/.build/x86_64-apple-macosx/debug/SwiftJWT.build/SwiftJWT-Swift.h"
           ^
${HOME}/dev/projects/private/Assist/Sources/Core/Networking/JWT.swift:10:8: error: could not build Objective-C module 'SwiftJWT'
import SwiftJWT
       ^
[6/35] Compiling Core JWT.swift

This happens when I build from console using swift build. When I build using Xcode everything works fine. Its about a command-line application.

Customize Algorithm

I want to sign jwt with secp256k1, how can I create a JWTSigner with secp256k1?

Issued At claim is greater than the current time

I'm occasionally getting the error 'Issued At claim is greater than the current time' when validating JWT claims.

I'm guessing this is because of clock skew because most of the time it works. However, occasionally this error crops up and breaks access to my API from my iOS app.

Is there a way of disabling IAT validation but leaving the rest of the validation in place?

For information, I'm validating a Firebase user token.

Missing Required Module 'OpenSSL' on Vapor.cloud and Heroku

Hi, I'm in the process of migrating a Swift command line app to now be a vapor app as I need to expose a couple API endpoints as well. The command line tool successfully uses the IBM-Swift/Swift-JWT and ideally would rather continue to use this. I've got the vapor app running on my Mac and under Xcode successfully (and the CLI), but when I attempt to deploy and build to vapor.cloud I get the error:

<unknown>:0: error: missing required module OpenSSL

however it does show its fetching openssl:

Fetching https://github.com/IBM-Swift/OpenSSL.git
Cloning https://github.com/IBM-Swift/OpenSSL.git
Resolving https://github.com/IBM-Swift/OpenSSL.git at 1.0.3

Is there something else I need to include in my Package.swift for this to build on Vapor.Cloud? Note that this same error appears on Heroku was well; I believe both are ubuntu instances.

Decode issue

I'm Sending the finalized JWT String in Header and expected to get a response as same
but it is changing the decode response
Screenshot 2022-01-20 at 11 22 40 AM

This is the cryptogram after encoding
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJhbW91bnQiOiIxLjAwIiwiZGV2aWNlSWQiOiJGRjY0QUUwOS02NkVDLTQ3QTMtODkwQy01MkE0RjE1MzFEOTEiLCJjcmVkaXRvckFjY291bnQiOiIyNTUyNTI1MjIiLCJlbmRUb0VuZElkIjoiQ01DTE1VTTAyMDIyMDEyMDAwMDAwMSIsImRlYnRvckFjY291bnQiOiIxMjM0NTY3OCIsImN1cnJlbmN5IjoiTVVSIiwiY29uc2VudElkIjoiODgzNzkifQ.GiIAaPBxa-Rsf6AjYWDVPpfvlqpau_qkADGHixskS2knONHDQv8wK1MleCcr4MViRcSCoSFl195BhqI9Pp4yE31OFd_O59O7FSDY1jt7ZIfkdZa9YHxz9QMgq-rk3f7S4m_REThgrTEVo9DsbTWNuuhE2XuJtKbovFxTFF_4_zftXWfoQ9bufW9BbLeUWwzLrUPrTKrPpon6DEy5nV0Sy-dufCJKt9X3-79La-2xgqPSjtybrQMlGg78gaVQF7tjya6dTrPMQ8j-TIyeaRdRQIsJm8xOl99wOEP7wA6JwxSqQsjeUTXRHPIikixcPTs8oybEbCh5qCZULz-LnOXYJw

if i see this decoding cryptogram in JWT, it is changing the json response

Screenshot 2022-01-20 at 11 26 00 AM

Migration guide for Swift-JWT v3.0

Swift-JWT 3.0.0 contains major API changes. We should provide a guide for how to migrate from the old API to the new one.

I'd recommend creating something like a migration.md and linking to this somewhere near the top of the README, perhaps just before the "Getting Started" section.

I'd also update the GitHub release notes for the 3.0.0 tag, to link to the guide.

error: 'SecCertificateCopyPublicKey' is only available on iOS 10.3 or newer

I folk this repo and try to make it support Carthage but when I run the build. There is an error like this

Swift-JWT/.build/checkouts/BlueRSA/Sources/CryptorRSA/CryptorRSAKey.swift:338:15: error: 'SecCertificateCopyPublicKey' is only available on iOS 10.3 or newer

let key = SecCertificateCopyPublicKey(certData)

decode fail

Doesnot decode if sub is inside an array!
This is my encoded text!
BI5ITZeEeyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJbe1wiYmFua0lkXCI6XCIwMzAxXCIsXCJyZWZCYW5rSWRcIjpcIkFEQkxcIixcImJhbmtOYW1lXCI6XCJBZ3JpY3VsdHVyZSBEZXZlbG9wbWVudCBCYW5rIEx0ZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MS4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiMTEwMVwiLFwicmVmQmFua0lkXCI6XCJCT0tcIixcImJhbmtOYW1lXCI6XCJCYW5rIG9mIEthdGhtYW5kdSBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjo1MzEuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjMxMDFcIixcInJlZkJhbmtJZFwiOlwiQ0NCTFwiLFwiYmFua05hbWVcIjpcIkNlbnR1cnkgQ29tbWVyY2lhbCBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjAuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjIwMDFcIixcInJlZkJhbmtJZFwiOlwiQ0lUSVpFTlNcIixcImJhbmtOYW1lXCI6XCJDaXRpemVucyBCYW5rIEludGVybmF0aW9uYWwgTGltaXRlZFwiLFwiZGViaXRDYXBcIjoyNTAwMDAwLjAwLFwiY2xyQmFsQW10XCI6NTAwMDAuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJtdW5uaW1ha2VyXCIsXCJsY2hnVGltZVwiOjE1Mzc0NDQwODM1ODksXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwibXVubmljaGVja2VyXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUzNzQ0NDEwNjExNH0se1wiYmFua0lkXCI6XCIzMDAxXCIsXCJyZWZCYW5rSWRcIjpcIkNJVklMXCIsXCJiYW5rTmFtZVwiOlwiQ2l2aWwgQmFuayBMdGQuXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjo0MDAxLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI1MDAxXCIsXCJyZWZCYW5rSWRcIjpcIk5ERVBcIixcImJhbmtOYW1lXCI6XCJEZXZhIEJpa2FzIEJhbmsgTGltaXRlZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6OTA1LjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIxMDAxXCIsXCJyZWZCYW5rSWRcIjpcIkVCTFwiLFwiYmFua05hbWVcIjpcIkV2ZXJlc3QgQmFuayBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjotODgwMDYuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJiaXNobnVcIixcImxjaGdUaW1lXCI6MTUyMjY0ODQ0NTE2NyxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIyNjQ5NTA0MTQzfSx7XCJiYW5rSWRcIjpcIjc1MDJcIixcInJlZkJhbmtJZFwiOlwiRVhDRUxcIixcImJhbmtOYW1lXCI6XCJFeGNlbCBEZXZlbG9wbWVudCBCYW5rIEx0ZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MTEuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjY2MDFcIixcInJlZkJhbmtJZFwiOlwiR0FSSU1BXCIsXCJiYW5rTmFtZVwiOlwiR2FyaW1hIEJpa2FzIEJhbmsgTGltaXRlZFwiLFwiZGViaXRDYXBcIjo5OTk5OTk5LjAwLFwiY2xyQmFsQW10XCI6MTEuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJiaXNobnVcIixcImxjaGdUaW1lXCI6MTUzMjIzNzYwNjQwMyxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTMyNTEyMTE3NTg2fSx7XCJiYW5rSWRcIjpcIjE5MDFcIixcInJlZkJhbmtJZFwiOlwiR0xPQkFMXCIsXCJiYW5rTmFtZVwiOlwiR2xvYmFsIElNRSBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjUwLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI3NTE0XCIsXCJyZWZCYW5rSWRcIjpcIkhBTVJPXCIsXCJiYW5rTmFtZVwiOlwiSEFNUk8gQklLQVMgQkFOSyBMSU1JVEVEXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjoyNTAwMDAwLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIwNzAxXCIsXCJyZWZCYW5rSWRcIjpcIkhCTFwiLFwiYmFua05hbWVcIjpcIkhpbWFsYXlhbiBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjEuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjk5MTlcIixcInJlZkJhbmtJZFwiOlwiOTkxOVwiLFwiYmFua05hbWVcIjpcIklDRkMgRmluYW5jZSBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjoxLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIyNzAxXCIsXCJyZWZCYW5rSWRcIjpcIkpBTkFUQVwiLFwiYmFua05hbWVcIjpcIkphbmF0YSBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjg5OC4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAyNzAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJiaXNobnVcIixcInJjcmVUaW1lXCI6MTUyMzg1NzM4NTM3NyxcImxjaGdVc2VySWRcIjpcImJpc2hudVwiLFwibGNoZ1RpbWVcIjoxNTIzODU3NDk4NDk3LFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjM4NTc1MDkzMDF9LHtcImJhbmtJZFwiOlwiNjAwMVwiLFwicmVmQmFua0lkXCI6XCJKQkJMXCIsXCJiYW5rTmFtZVwiOlwiSnlvdGkgQmlrYXNoIEJhbmsgTHRkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjo0MDAyLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI2ODAxXCIsXCJyZWZCYW5rSWRcIjpcIktBTUFOQVwiLFwiYmFua05hbWVcIjpcIkthbWFuYSBTZXdhIEJpa2FzIEJhbmsgTHRkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjoxLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI5OTQ1XCIsXCJyZWZCYW5rSWRcIjpcIktBTkNIQU5cIixcImJhbmtOYW1lXCI6XCJLYW5jaGFuIERldmVsb3BtZW50IEJhbmsgTHRkXCIsXCJkZWJpdENhcFwiOjEwMDAwMDAuMDAsXCJjbHJCYWxBbXRcIjotMTk1MDUuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjc1MTVcIixcInJlZkJhbmtJZFwiOlwiS0FOS0FJXCIsXCJiYW5rTmFtZVwiOlwiS2Fua2FpIEJpa2FzIEJhbmsgTHRkXCIsXCJkZWJpdENhcFwiOjEwMDAwLjAwLFwiY2xyQmFsQW10XCI6MTAwMDAuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjE2MDFcIixcInJlZkJhbmtJZFwiOlwiS1VNQVJJXCIsXCJiYW5rTmFtZVwiOlwiS3VtYXJpIEJhbmsgTHRkLlwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MzQuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjE3MDFcIixcInJlZkJhbmtJZFwiOlwiTEFYTUlcIixcImJhbmtOYW1lXCI6XCJMYXhtaSBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MTAwMDAwLjAwLFwiY2xyQmFsQW10XCI6LTI4MDExLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI1NDAxXCIsXCJyZWZCYW5rSWRcIjpcIlZJQk9SXCIsXCJiYW5rTmFtZVwiOlwiTHVtYmluaSBCaWthcyBCYW5rIEx0ZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MTQzNi4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiMTUwMVwiLFwicmVmQmFua0lkXCI6XCJNUEJMXCIsXCJiYW5rTmFtZVwiOlwiTWFjaGhhcHVjaHJlIEJhbmsgTGltaXRlZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MTAxLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI5OTMxXCIsXCJyZWZCYW5rSWRcIjpcIk1BSEFcIixcImJhbmtOYW1lXCI6XCJNYWhhbGF4bWkgQmlrYXNoIEJhbmsgTHRkLlwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MS4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiOTkzNVwiLFwicmVmQmFua0lkXCI6XCI5OTM1XCIsXCJiYW5rTmFtZVwiOlwiTWFuanVzaHJlZSBGaW5hbmNlIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MTAwMDAwLjAwLFwiY2xyQmFsQW10XCI6MTAwMDAwLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIyODAxXCIsXCJyZWZCYW5rSWRcIjpcIk1FR0FcIixcImJhbmtOYW1lXCI6XCJNZWdhIEJhbmsgTmVwYWwgTHRkLlwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MS4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiNzIwMVwiLFwicmVmQmFua0lkXCI6XCJNQkJMXCIsXCJiYW5rTmFtZVwiOlwiTXVrdGluYXRoIEJpa2FzIEJhbmsgTGltaXRlZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MTEuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjA0MDFcIixcInJlZkJhbmtJZFwiOlwiTkFCSUxcIixcImJhbmtOYW1lXCI6XCJOYWJpbCBCYW5rIEx0ZC5cIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjMyMTU3NzguMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjA5MDFcIixcInJlZkJhbmtJZFwiOlwiTkJCXCIsXCJiYW5rTmFtZVwiOlwiTmVwYWwgQmFuZ2xhZGVzaCBCYW5rIEx0ZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MTg1NzAuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjAxMDFcIixcInJlZkJhbmtJZFwiOlwiTkJMXCIsXCJiYW5rTmFtZVwiOlwiTmVwYWwgQmFuayBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjo1MDEuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjEyMDFcIixcInJlZkJhbmtJZFwiOlwiTkNDQlwiLFwiYmFua05hbWVcIjpcIk5lcGFsIENyZWRpdCBhbmQgQ29tbWVyY2UgQmFuayBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjoxNTIyLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIwNTAxXCIsXCJyZWZCYW5rSWRcIjpcIk5JQkxcIixcImJhbmtOYW1lXCI6XCJOZXBhbCBJbnZlc3RtZW50IEJhbmsgTGltaXRlZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6NzAxOS4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiMjMwMVwiLFwicmVmQmFua0lkXCI6XCJOSUNBXCIsXCJiYW5rTmFtZVwiOlwiTklDIEFzaWEgQmFuayBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjo1MjEwLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIyNTAxXCIsXCJyZWZCYW5rSWRcIjpcIk5NQlwiLFwiYmFua05hbWVcIjpcIk5NQiBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MTAwMC4wMCxcImNsckJhbEFtdFwiOi0yNDM5Ny4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiNjcwMVwiLFwicmVmQmFua0lkXCI6XCJPREJMXCIsXCJiYW5rTmFtZVwiOlwiT20gRGV2ZWxvcG1lbnQgQmFuayBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjowLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIyNjAxXCIsXCJyZWZCYW5rSWRcIjpcIlBCTFwiLFwiYmFua05hbWVcIjpcIlByYWJodSBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjE5LjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIyMTAxXCIsXCJyZWZCYW5rSWRcIjpcIlBSSU1cIixcImJhbmtOYW1lXCI6XCJQcmltZSBDb21tZXJjaWFsIEJhbmsgTGltaXRlZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6NTAwLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI5OTEyXCIsXCJyZWZCYW5rSWRcIjpcIjk5MTJcIixcImJhbmtOYW1lXCI6XCJQdXJuaW1hIEJpa2FzIEJhbmsgTGltaXRlZFwiLFwiZGViaXRDYXBcIjoxLjAwLFwiY2xyQmFsQW10XCI6MTYuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjAyMDFcIixcInJlZkJhbmtJZFwiOlwiUkJCXCIsXCJiYW5rTmFtZVwiOlwiUmFzdHJpeWEgQmFuaWp5YSBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjEuMDAsXCJlbmFibGVkXCI6XCJZXCIsXCJvdHBPcmlnaW5cIjpcIk5DSExcIixcImFwaUJhc2VVcmxcIjpcImh0dHA6Ly8xMC4yNTAuMy4xNzo2MDgwL2Nvbm5lY3RpcHNzcnZjL2FwaS9iYW5rL1wiLFwiYXBpVXNlcklkXCI6XCJBUElAMTAwMVwiLFwiYXBpUGFzc3dvcmRcIjpcIkFiY0AxMjNcIixcImlud2FyZEludGVncmF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50SW5xdWlyeW5FbmFibGVkXCI6XCJOXCIsXCJhY2NvdW50VmFsaWRhdGlvbkFwaUJhc2VVcmxcIjpudWxsLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjk5MzlcIixcInJlZkJhbmtJZFwiOlwiUkVMRkxcIixcImJhbmtOYW1lXCI6XCJSZWxpYW5jZSBGaW5hbmNlIEx0ZC5cIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjk5MDUwMC4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiNDUwMVwiLFwicmVmQmFua0lkXCI6XCJTQU5JTUFcIixcImJhbmtOYW1lXCI6XCJTYW5pbWEgQmFuayBMdGQuXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjo2LjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjEyOS44NTo4MDgwL2FwaS9uY2hsL3ZhbGlkYXRlYWNjb3VudFwiLFwicmNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJyY3JlVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJsY2hnVXNlcklkXCI6XCJzdWJhc2hcIixcImxjaGdUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImVudGl0eUNyZUZsZ1wiOlwiWVwiLFwiZW50aXR5Q3JlVXNlcklkXCI6XCJzdWJhc2hcIixcImVudGl0eUNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwfSx7XCJiYW5rSWRcIjpcIjczMDFcIixcInJlZkJhbmtJZFwiOlwiU0dEQkxcIixcImJhbmtOYW1lXCI6XCJTaGFuZ3JpbGEgRGV2ZWxvcG1lbnQgQmFuayBMaW1pdGVkXCIsXCJkZWJpdENhcFwiOjEuMDAsXCJjbHJCYWxBbXRcIjowLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCI4MTAxXCIsXCJyZWZCYW5rSWRcIjpcIlNSREJMXCIsXCJiYW5rTmFtZVwiOlwiU2hpbmUgUmVzdW5nYSBEZXZlbG9wbWVudCBCYW5rIEx0ZC5cIixcImRlYml0Q2FwXCI6MTAwMDAwLjAwLFwiY2xyQmFsQW10XCI6NDAxLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiTlwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH0se1wiYmFua0lkXCI6XCIxODAxXCIsXCJyZWZCYW5rSWRcIjpcIlNJREJMXCIsXCJiYW5rTmFtZVwiOlwiU2lkZGhhcnRoYSBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjIxMzgzMS4wMCxcImVuYWJsZWRcIjpcIllcIixcIm90cE9yaWdpblwiOlwiTkNITFwiLFwiYXBpQmFzZVVybFwiOlwiaHR0cDovLzEwLjI1MC4zLjE3OjYwODAvY29ubmVjdGlwc3NydmMvYXBpL2JhbmsvXCIsXCJhcGlVc2VySWRcIjpcIkFQSUAxMDAxXCIsXCJhcGlQYXNzd29yZFwiOlwiQWJjQDEyM1wiLFwiaW53YXJkSW50ZWdyYXRpb25FbmFibGVkXCI6XCJZXCIsXCJhY2NvdW50VmFsaWRhdGlvbkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRJbnF1aXJ5bkVuYWJsZWRcIjpcIk5cIixcImFjY291bnRWYWxpZGF0aW9uQXBpQmFzZVVybFwiOm51bGwsXCJyY3JlVXNlcklkXCI6XCJzdWJhc2hcIixcInJjcmVUaW1lXCI6MTUyMTAyOTcwMDAwMCxcImxjaGdVc2VySWRcIjpcInN1YmFzaFwiLFwibGNoZ1RpbWVcIjoxNTIxMDI5NzAwMDAwLFwiZW50aXR5Q3JlRmxnXCI6XCJZXCIsXCJlbnRpdHlDcmVVc2VySWRcIjpcInN1YmFzaFwiLFwiZW50aXR5Q3JlVGltZVwiOjE1MjEwMjk3MDAwMDB9LHtcImJhbmtJZFwiOlwiMjIwMVwiLFwicmVmQmFua0lkXCI6XCJTVU5SXCIsXCJiYW5rTmFtZVwiOlwiU3VucmlzZSBCYW5rIExpbWl0ZWRcIixcImRlYml0Q2FwXCI6MS4wMCxcImNsckJhbEFtdFwiOjE2OTgwLjAwLFwiZW5hYmxlZFwiOlwiWVwiLFwib3RwT3JpZ2luXCI6XCJOQ0hMXCIsXCJhcGlCYXNlVXJsXCI6XCJodHRwOi8vMTAuMjUwLjMuMTc6NjA4MC9jb25uZWN0aXBzc3J2Yy9hcGkvYmFuay9cIixcImFwaVVzZXJJZFwiOlwiQVBJQDEwMDFcIixcImFwaVBhc3N3b3JkXCI6XCJBYmNAMTIzXCIsXCJpbndhcmRJbnRlZ3JhdGlvbkVuYWJsZWRcIjpcIllcIixcImFjY291bnRWYWxpZGF0aW9uRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudElucXVpcnluRW5hYmxlZFwiOlwiWVwiLFwiYWNjb3VudFZhbGlkYXRpb25BcGlCYXNlVXJsXCI6bnVsbCxcInJjcmVVc2VySWRcIjpcInN1YmFzaFwiLFwicmNyZVRpbWVcIjoxNTIxMDI5NzAwMDAwLFwibGNoZ1VzZXJJZFwiOlwic3ViYXNoXCIsXCJsY2hnVGltZVwiOjE1MjEwMjk3MDAwMDAsXCJlbnRpdHlDcmVGbGdcIjpcIllcIixcImVudGl0eUNyZVVzZXJJZFwiOlwic3ViYXNoXCIsXCJlbnRpdHlDcmVUaW1lXCI6MTUyMTAyOTcwMDAwMH1dIn0.6b6qN0Hr_Aqu6IFt3qgnQWJquiDLND1MeegsdWS16YQpLB8POSbY7fbAKM_UTXeUcCjtrUNNXTaFQOgXqIMOwwjSj0bu.MHxzI3Ezr

JSON issue

I'm Sending the finalized JWT String in Header and expected to get a response as

{
AccessToken = "";
AppType = 0;
BusinessId = "66d139e5-7797-4d37-8a9a-368df35f3664";
BusinessStatus = 0;
ContactName = "Mike Andrew";
ContactNameDisplayFormat = "";
}

but I'm getting

{
accessToken = "";
appType = 0;
businessId = "66d139e5-7797-4d37-8a9a-368df35f3664";
businessStatus = 0;
contactName = "Mike Andrew";
contactNameDisplayFormat = "";
}

JWTDecoder Fatal error: Index out of range

The JWTDecoder.decode method currently checks for the existence of headers and claims but it does so by assuming the array of strings has a count of at least 2. Therefore, passing an empty/malformed string causes a fatal error. I propose adding a guard to verify the array's count before attempting to access the strings.

Is a fix for this in the works? If not, I will submit a PR.

Fatal error: invalid unsafeDowncast

On creation jwt - iOS 12.0

FILE:
BlueECC -> ECPrivateKey.swift

CODE: 447-463
#else
let keyData = publicKeyData + privateKeyData
var error: Unmanaged? = nil
guard let secKey = SecKeyCreateWithData(keyData as CFData,
[kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass: kSecAttrKeyClassPrivate] as CFDictionary,
&error)
else {
if let secError = error?.takeRetainedValue() {
throw secError
} else {
throw ECError.failedNativeKeyCreation
}
}
return secKey
#endif
}

Update 3.6.201 in Cocoapods?

Cocoapods is currently showing v. 3.6.200.

Just looking for getting 3.6.201 published into cocoapods.

-Thanks!

Problem with with signing myJWT with private key -> JWTSigner.rs512

Hello :),

Great library but I have some problems. I always get an error when I try to get the PRIVATE key as a Swift variable. I get the reference to the public and private key and public key data, but cannot do the same for the private key (there is no existing method like for the "getPublicKeyData()" and the one I implemented is not working).

The error I get is:
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: SwiftJWT.JWTError(localizedDescription: "Provided private key could not be used to sign JWT", internalError: SwiftJWT.(unknown context at 0x10d9ae418).InternalError.invalidPrivateKey)

Here is code I am using where "payloadString" is data I am trying to transfer:

kRSASwiftGeneratorApplicationTag = "MY.BUNDLE.ID"
let myHeader = Header()

struct MyClaims: Claims {
            let payloadString: String
        }
let payloadData = try! JSONSerialization.data(withJSONObject: payload, options: [])
let payloadString = payloadData.base64EncodedString(options: [])
let myClaims = MyClaims(payloadString: payloadString)

let getPublicKeyData = RSASwiftGenerator.shared.getPublicKeyData()
let getPublicKeyReference = RSASwiftGenerator.shared.getPublicKeyReference()
let getPrivateKeyReference = RSASwiftGenerator.shared.getPrivateKeyReference()

here is the custom par I tried for getting private key as Data

var dataPtr:CFTypeRef?
        let query: [String: Any] = [
            kSecClass as String: kSecClassKey,
            kSecAttrApplicationTag as String: "MY.BUNDLE.ID",
            kSecReturnData as String: true
        ]

        let qResult = SecItemCopyMatching(query as CFDictionary, &dataPtr)
        let data = dataPtr as! Data
        let base64PublicKey = data.base64EncodedString()

Now again back to your library:

        let jwtSigner = JWTSigner.rs512(privateKey: data)
        var myJWT = JWT(header: myHeader, claims: myClaims)
        let signedJWT = try! myJWT.sign(using: jwtSigner)

On the last instruction " try! myJWT.sign(using: jwtSigner)" I get an error.

Is there something I overlooked. In instructions on your site you have how to get the private key as data but that is from the local path on MAC. I am not sure how can I use that from the phone to get the PRIVATE key as a Swift variable.

let privateKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/privateKey.key"))
let privateKey: Data = try Data(contentsOf: privateKeyPath, options: alwaysMapped)
let publicKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/publicKey.key"))
let publicKey: Data = try Data(contentsOf: publicKeyPath, options: alwaysMapped)

Just also to add, if I generate pub private keys on my mac as you wrote, and get them with path, for example:

let privateKeyPathMac = URL(fileURLWithPath: "/Users/pm/.ssh/privateKey.key")
        let privateKeyMac: Data = try! Data(contentsOf: privateKeyPathMac)

I get an error:

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error code: -9997(0x-270D), Provided key doesn't have a valid ASN.1 structure (first byte should be 0x30 == SEQUENCE)

RSA private key creation from data failed

I'm having a tough time using this lib. I'm trying to generate JWT using Google Private key.
My approach below:

let key = "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDSm9uzsHb4u257\n6GEiWntLseb9cgKYNujPt725YtGXQx7EtbD6L7/L6I/aTH1w1E1gZqK6XRzIkiZm\nPBxYoOuT9K89LUzmSGaIFqwUpqPMDrOssyKxNHCf9fRHNCREKyTWMHUZ/2Rt/cMd\nTniljA572KhenaY5C0sqhdTrEQnc8xKMKwInSoxI2wg4HwbBectMp/5L3B0wsGgH\nGkFunGFKjMkOQ4VUcv+7V9BHfJLcFaSKs+/q03RHJAxijP5joMnNBEWi9s/giCvr\npEdvgoMkt6NE+6am3yRFZTFYIf7/Z5nxSW4qKdhfSjIvDrcv3qo7aCgbf7wNiVxH\nPmE2Fo9XAgMBAAECggEBALFjAu5a4CnpvEny1PVZXmXIBrVLdLH99aMWsF7Xw45y\nwxSNr+1ZkGLPk3IbYMBKoI1khQUQ7fBlYKBVWs6vYxwwR/TwFcgUDP/skK2oGWgC\nrgT0sHCuqXmhcEkUusMLz6/0Cn2GJXGa/d7OPEG7MGvRdSaUA/Ah+gJrzITcygDk\n1rSbeHiiFjhPSsAZ5fYOE5j/GGML/efRDLSfDE7vtHWp42s0Oe9eLMMmgQbEW82z\nVhBqeOjQkHVxDhr3ag6MXy5n5MDrkMbh3HVyGeV64tpHXs4M5N1iL+e3YN9aMC07\nyuZuaLsjHC/Sglla1KtDR814wQ5174p/bowOB/GyHekCgYEA94yauOdIlFiv2A3b\n9VTvYgmlNFrmo5M3AeHRkhDjQdo0+JnzT1KLfdTQ7gTFCZ66xPbiK2UzmbXFNIDc\ngf25vQ5LxrKFRqjJcocg6KcpV3KCWkONB5Sh9+FvNFIO//6LCuYM2Hvfjv5degZH\nrWFtQTQV3XgHrECwgY1iprlD7S0CgYEA2cxsEvgZ55oj8sS+MPAU2G7sNK3Cs3Z+\ndzWiGMmHJihBskamyvJOmFYkizjwUXhjcL2ZOicldQ5xqSpQe+zYeXuq405UNUuZ\n2QVQ2EezzhPSoofzrxMrwKtng3SKdTVx1qny5i0M4ZEzWgu2N466yLdTolGzWdSw\njoCIaTim6RMCgYEAnwOwt6nJ05EMk6qDapo+kylC99iUYurD4O+f4UX71WdHs5Gg\n24lYlWHJO7vQnhdaPf+g1ONTPB+pJ8rG2rGTSEAQqPgv6G2vyWPH3erTAZtK5JST\n2RS+3i3vcxprDEIEKuIPylf4CTCX9zRlgpgcyE+e4/6gXyPGvdGGVzaWzZkCgYAE\noELrZDmooa2Byov/nhnTPwflVot8JFgrUAhRXnZwaQp8LuP8C4l/0tST4HG6SURT\ncLOAeLRi+BuR7EQpXa57ZhULHu7K8wAhi+tbrKo1BlbC/QBAB7g2L23TbPZD5w6z\n8IgoO2y6ncrpbrZAF9f/y2ULXZDhp5LYdAJxubJR4QKBgFoZYEzqiEYO/MwdzrVy\n11tWGzy6NsAEGv6EBg0cIsdyg2gbzuMBsKcIrwsT9v0BTl+H4gdDALvijQOPfyJM\nQJGXamigBDjvCfMluWHzbYH/YbyRjUklhJwGQIEu12uSK8tIGd9EvR1g4ZkR4h5x\nZowPmeBkmJMQvZc0OEiP4fJb\n-----END PRIVATE KEY-----\n"
  
let payload =  OAuthPayload(iss: Current.envVars.google.clientEmail, scope: "https://www.googleapis.com/auth/calendar.events", aud: "https://www.googleapis.com/oauth2/v4/token", iat: Date(), exp: Date().addingTimeInterval(3600))
  
var jwt = JWT<OAuthPayload>.init(claims: payload)
let signer = JWTSigner.rs256(privateKey: key.data(using: .utf8)!)
let jwtString = try! jwt.sign(using: signer)
  
print(jwtString)

I'm getting this error:

Error Domain=NSOSStatusErrorDomain Code=-50 "RSA private key creation from data failed" (paramErr: error in user parameter list) UserInfo={NSDescription=RSA private key creation from data failed}

Any idea what am I doing wrong?

Provided private key could not be used to sign JWT

Hello,
i tried creating a JWT with the following code from your documentation:

let path = Bundle.main.path(forResource: "privateKey", ofType: "key")
let privateKeyPath = URL(fileURLWithPath: path!)
let privateKey: Data = try Data(contentsOf: privateKeyPath, options: .alwaysMapped)
let jwtSigner = JWTSigner.rs256(privateKey: privateKey)
let signedJwt = try jwt.sign(using: jwtSigner)

but at the last line i get an exception telling me that the 'Provided private key could not be used to sign JWT'.
I've first tried a key that has always worked in java and then a key generated with
ssh-keygen -t rsa -b 4096 -m PEM -f privateKey.key
The second one is much longer, but both keys produce the same result.

Create/verify JWT tokens with dynamic claims/header?

Hi, I'm writing an app to create a signed JWT token from the user's input header, claims, and secret. By reading through the document, I found out the only way to create/verify a token is to have a predefined Claims class and all other APIs are around the assumption that there is a fixed Claims class defined.

Since the header, claims, and secret are provided by the user at runtime, I couldn't find a way to create a JWT token using this library. Am I missing something? Is there a way to create/verify a token with a dynamic claims/header?

Thanks for your time.

Can't install Swift-JWT through Pod

I tried installing with pod but I get this message:

Specs satisfying the `SwiftJWT` dependency were found, but they required a higher minimum deployment target.

This is on a newly created project with Xcode 11.2.1

Date() displayed wrong

Hello,
I am using a "hs256" algorithm and, when I make creating a clame, my Date, for example Date() displays correctly in the code, but when I put it in a claim like
var jwt = JWT(claims: AdminClaims(sub: "Kitura", isAdmin: true, exp: Date()))
I get a weird time of year 1988 which I can see when I paste the complete JWT string to https://jwt.io/

I had no problems with other libraries recommended from JWT in this sense, but this is most up to date and I would like to use it if this is solvable.

for example this is the code

    let myHeader = Header(kid: "KeyID1")

    struct AdminClaims: Claims {
        var sub: String
        var isAdmin: Bool
        var exp: Date
    }
    
    let expDate = Date(timeIntervalSinceNow: 60)
    var jwt = JWT(header: myHeader, claims: AdminClaims(sub: "Kitura", isAdmin: true, exp: expDate))

    let secretData = "test123".data(using: .utf8)!
    let jwtSigner = JWTSigner.hs256(key: secretData)
    let signedJWT = try! jwt.sign(using: jwtSigner)

and I get this jwt string

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IktleUlEMSJ9.eyJzdWIiOiJLaXR1cmEiLCJpc0FkbWluIjp0cnVlLCJleHAiOjU2ODcxNDEwNi40OTkwOTk5N30.55r0oXo4hPDLbErDpZgdSaUGpIWylPuz9YpCcGywrO8

Crash on Ubuntu 16.04

I am trying to sign a jwt to ask for a google access token but it seems as though the signer is returning nil when it is not supposed to.

Stacktrace

[DEBUG] Signing private key (/app/.build/checkouts/SwiftyFire.git--980980914125235142/Sources/SwiftyFire/Secrets.swift:createJWT():53:26)
Fatal error: Unexpectedly found nil while unwrapping an Optional value
Current stack trace:
0    libswiftCore.so                    0x00007f57f52d5120 _swift_stdlib_reportFatalError + 168
1    libswiftCore.so                    0x00007f57f502cd0a <unavailable> + 1502474
2    libswiftCore.so                    0x00007f57f526a19e <unavailable> + 3850654
3    libswiftCore.so                    0x00007f57f502cd0a <unavailable> + 1502474
4    libswiftCore.so                    0x00007f57f51c50d9 <unavailable> + 3174617
5    libswiftCore.so                    0x00007f57f502c7d0 _fatalErrorMessage(_:_:file:line:flags:) + 19

Secrets.swift:createJWT()

    private func createJWT() -> String? {
        let myClaims = MyClaims(iss: firebaseServiceAccount,
                                scope: "https://www.googleapis.com/auth/firebase.database https://www.googleapis.com/auth/userinfo.email",
                                exp: Int(Date().addingTimeInterval(60 * 30).timeIntervalSince1970),
                                aud: "https://www.googleapis.com/oauth2/v4/token",
                                iat: Int(Date().timeIntervalSince1970))
        let header = Header(typ: "JWT")
        var myJWT = JWT(header: header, claims: myClaims)
        do {
            guard let privateKey = googlePrivateKey else { return nil }
            let jwtSigner = JWTSigner.rs256(privateKey: privateKey)
            logger.debug("Signing private key")
            return try myJWT.sign(using: jwtSigner) // <- Fatal Error
        } catch  {
            return nil
        }
    }

Dockerfile

FROM swift:4.2

RUN apt-get -qq update && apt-get -q -y install \
  tzdata \
  && rm -r /var/lib/apt/lists/*

SwiftJWT causing exceptions for iOS 12.4 devices

Note that this currently applies to iOS 12.4 devices. iOS 13+ devices have not had this issue reported. It seems CryptorECC, which the SwiftJWT library uses, is the culprit.

Has anyone also encountered this?

Relevant trace posted below:

Date/Time:           2020-05-09 00:15:57.1893 -0400
Launch Time:         2020-05-09 00:15:55.7345 -0400
OS Version:          iPhone OS 12.4.4 (16G140)
Baseband Version:    n/a
Report Version:      104

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000259a73b00
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [2416]
Triggered by Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libswiftCore.dylib            	0x0000000259a73b00 0x259870000 + 2112256
1   libswiftCore.dylib            	0x0000000259a73b00 0x259870000 + 2112256
2   libswiftCore.dylib            	0x0000000259aa5300 0x259870000 + 2315008
3   libswiftCore.dylib            	0x00000002598f1f70 0x259870000 + 532336
4   CryptorECC                    	0x0000000100d1d9fc 0x100d14000 + 39420
5   CryptorECC                    	0x0000000100d1ec9c 0x100d14000 + 44188
6   CryptorECC                    	0x0000000100d1b5dc 0x100d14000 + 30172
7   SwiftJWT                      	0x00000001011242c8 0x10111c000 + 33480
8   SwiftJWT                      	0x00000001011240ec 0x10111c000 + 33004
9   SwiftJWT                      	0x0000000101124514 0x10111c000 + 34068
10  SwiftJWT                      	0x0000000101137a5c 0x10111c000 + 113244

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.